diff --git a/.env.example b/.env.example index b10316ce..69c3bb9d 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ -RPC_URL=https://testnet.ixo.earth/rpc/ -RPC_URL=https://impacthub-rpc.lavenderfive.com/ -RPC_URL=http://localhost:26658/ +RPC_URL=https://testnet.ixo.earth/rpc/ #https://impacthub-rpc.lavenderfive.com/ #http://localhost:26658/ # NEVER COMMIT MAINNET MNENOMICS!! Please be careful. +TESTER_MNEMONIC-"mango tattoo civil foam frog wheat venue rebuild cloth example alien taste" +ED_KEYS_MNEMONIC="office dance method praise twenty flush bacon stereo claw music what satisfy" IBC_FROM_MNEMONIC="mango tattoo civil foam frog wheat venue rebuild cloth example alien taste" IBC_TO_ADDRESS=ixo1tumrhpa5tpegdcs2nhwzft8maprttz66pvntc9 diff --git a/.eslintrc.js b/.eslintrc.js index 2718e8bc..c959a328 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -64,7 +64,7 @@ module.exports = { { trailingComma: 'none', singleQuote: true, - printWidth: 80 + printWidth: 120 } ] } diff --git a/__tests__/flows/claims.ts b/__tests__/flows/claims.ts index 1717c075..36f84ac5 100644 --- a/__tests__/flows/claims.ts +++ b/__tests__/flows/claims.ts @@ -13,6 +13,7 @@ export const claimsBasic = () => const res = await Entity.CreateEntity( "protocol", undefined, + "", WalletUsers.charlie ); protocol = utils.common.getValueFromEvents(res, "wasm", "token_id"); @@ -130,6 +131,7 @@ export const devnetClaims = () => const res = await Entity.CreateEntity( "protocol", undefined, + "", WalletUsers.charlie ); protocol = utils.common.getValueFromEvents(res, "wasm", "token_id"); diff --git a/__tests__/flows/cosmos.ts b/__tests__/flows/cosmos.ts index 09d9bcca..5118ca8e 100644 --- a/__tests__/flows/cosmos.ts +++ b/__tests__/flows/cosmos.ts @@ -5,15 +5,17 @@ import { WalletUsers } from "../helpers/constants"; export const bankBasic = () => describe("Testing the cosmos bank module", () => { - testMsg("/cosmos.bank.v1beta1.MsgSend", () => - Cosmos.BankSendTrx( + testMsg("/cosmos.bank.v1beta1.MsgSend", async () => { + const res = await Cosmos.BankSendTrx( undefined, WalletUsers.tester, WalletUsers.tester, "secp", "ed" - ) - ); + ); + console.log(res); + return res; + }); }); export const authzBasic = () => @@ -55,6 +57,6 @@ export const sendTokens = () => }); export const govDeposit = () => - describe("/cosmos.gov.v1beta1.MsgDeposit", () => { - testMsg("/cosmos.bank.v1beta1.MsgSend", () => Cosmos.MsgDeposit(404)); + describe("Testing deposit funds into proposals", () => { + testMsg("/cosmos.bank.v1beta1.MsgDeposit", () => Cosmos.MsgDeposit(434)); }); diff --git a/__tests__/flows/entities.ts b/__tests__/flows/entities.ts index d8a4b268..80a35a4a 100644 --- a/__tests__/flows/entities.ts +++ b/__tests__/flows/entities.ts @@ -123,7 +123,7 @@ export const supamotoEntities = () => // Save supamoto credsPdf WEB3 let projectCertDoc = - "https://bafkreiefafy2u5df4l52yb7vvz32hxrxhcceyaq3z7xww2qlz2fp3ppeum.ipfs.w3s.link"; + "bafkreiefafy2u5df4l52yb7vvz32hxrxhcceyaq3z7xww2qlz2fp3ppeum"; test("Saving projectCertDoc", async () => { projectCertDoc = ( await customQueries.cellnode.uploadWeb3Doc( @@ -136,14 +136,13 @@ export const supamotoEntities = () => undefined, cellNodeNetwork ) - ).url; + ).cid; console.log({ projectCertDoc }); expect(projectCertDoc).toBeTruthy(); }); // Save supamoto profile WEB3 - let profile = - "https://bafkreib5ka542u2ousereo23hr77qfaohtn2inhkr436u74rqzsktefynm.ipfs.w3s.link"; + let profile = "4kavdefz12wlefltwxr"; test("Saving profile", async () => { const file = JSON.parse( getFileFromPath(["documents", "test-supamoto-profile.jsonld"], "ascii") @@ -152,19 +151,18 @@ export const supamotoEntities = () => file["logo"] = supaLogo; let buff = Buffer.from(JSON.stringify(file)); profile = ( - await customQueries.cellnode.uploadWeb3Doc( - utils.common.generateId(12), + await customQueries.cellnode.uploadPublicDoc( "application/ld+json", buff.toString("base64"), undefined, cellNodeNetwork ) - ).url; + ).key; console.log({ profile }); expect(profile).toBeTruthy(); }); - // Save supamoto creator CELLNODE + // Save supamoto creator CELLNODE emerging cellnode let creator = "4kavdefz12wlefltwxr"; test("Saving creator", async () => { const tester = getUser(); @@ -230,7 +228,7 @@ export const supamotoEntities = () => // Save supamoto projectCreds WEB3 let projectCreds = - "https://bafkreih2oq64xhbgp7vyarcrgw6dcofms4zdmjqms6vnfx32vzwglj6nd4.ipfs.w3s.link"; + "bafkreih2oq64xhbgp7vyarcrgw6dcofms4zdmjqms6vnfx32vzwglj6nd4"; test("Saving projectCert", async () => { const file = JSON.parse( getFileFromPath( @@ -243,8 +241,8 @@ export const supamotoEntities = () => "credentialSubject" ]["project"]["linkedResources"].map((lr: any) => ({ ...lr, - id: projectCertDoc, - proof: projectCertDoc.split(".")[0].split("/")[2], + id: `https://ipfs.io/ipfs/${projectCertDoc}`, + proof: projectCertDoc, })); let buff = Buffer.from(JSON.stringify(file)); projectCreds = ( @@ -255,7 +253,7 @@ export const supamotoEntities = () => undefined, cellNodeNetwork ) - ).url; + ).cid; console.log({ projectCreds }); expect(projectCreds).toBeTruthy(); }); @@ -275,9 +273,9 @@ export const supamotoEntities = () => expect(tags).toBeTruthy(); }); - // Save supamoto tokenMetadata WEB3 + // Save supamoto tokenMetadata WEB3 emerging account let tokenMetadata = - "https://bafkreie7kbpppoizx7anxxufblfkdfmuy27mppuz2hq4a4uouudweb2sm4.ipfs.w3s.link"; + "bafkreie7kbpppoizx7anxxufblfkdfmuy27mppuz2hq4a4uouudweb2sm4"; test("Saving tokenMetadata", async () => { const file = JSON.parse( getFileFromPath( @@ -296,7 +294,7 @@ export const supamotoEntities = () => undefined, cellNodeNetwork ) - ).url; + ).cid; console.log({ tokenMetadata }); expect(tokenMetadata).toBeTruthy(); }); @@ -319,7 +317,7 @@ export const supamotoEntities = () => // Create a base Protocol entity let protocolDid = "did:ixo:entity:065ba0b99948e2e8ff3228836dee423b"; testMsg("/ixo.entity.v1beta1.MsgCreateEntity protocol", async () => { - const res = await Entity.CreateEntity("protocol"); + const res = await Entity.CreateEntity("protocol/asset"); protocolDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); console.log({ protocolDid }); return res; @@ -331,14 +329,14 @@ export const supamotoEntities = () => const res = await Entity.CreateEntityAssetSupamoto({ inheritEntityDid: protocolDid, profile, - page, - creator, - administrator, + // page, + // creator, + // administrator, tags, claims, tokenMetadata, projectCert: projectCreds, - oracle: daoCredsIssuerDid, + oracles: [daoCredsIssuerDid], }); protocolAssetDid = utils.common.getValueFromEvents( res, @@ -388,7 +386,9 @@ export const supamotoEntities = () => file["credentialSubject"]["id"] = ( file["credentialSubject"]["id"] as string ).replace("deviceId", id); - file["credentialSubject"]["certification"]["id"] = projectCertDoc; + file["credentialSubject"]["certification"][ + "id" + ] = `https://ipfs.io/ipfs/${projectCertDoc}`; let buff = Buffer.from(JSON.stringify(file)); deviceCreds = ( await customQueries.cellnode.uploadWeb3Doc( @@ -398,7 +398,7 @@ export const supamotoEntities = () => undefined, cellNodeNetwork ) - ).url; + ).cid; console.log({ deviceCreds }); if (!deviceCreds) throw new Error("error saving device creds file"); diff --git a/__tests__/flows/iids.ts b/__tests__/flows/iids.ts index d1348c3c..44857d4d 100644 --- a/__tests__/flows/iids.ts +++ b/__tests__/flows/iids.ts @@ -38,14 +38,6 @@ export const registerIids = () => Iid.CreateIidDoc(user) ); }); - - // testQry( - // "test query", - // () => queryClient.ixo.bonds.v1beta1.bond({ bondDid: "adsf" }), - // { - // bonds: [], - // } - // ); }); // ------------------------------------------------------------ @@ -107,6 +99,14 @@ export const iidsBasic = () => testMsg("/ixo.iid.v1beta1.MsgDeleteService", () => Iid.DeleteService()); }); +export const iidAddEdKeys = () => + describe("Testing the Iid module adding ED keys to iid doc", () => { + testMsg("/ixo.iid.v1beta1.MsgAddVerification", () => Iid.AddVerification()); + // testMsg("/ixo.iid.v1beta1.MsgRevokeVerification", () => + // Iid.RevokeVerification() + // ); + }); + export const generateBlockchainTestUsers = () => { beforeAll(() => generateNewWallet( diff --git a/__tests__/flows/quickQueries.ts b/__tests__/flows/quickQueries.ts index 8027c3ba..f52add05 100644 --- a/__tests__/flows/quickQueries.ts +++ b/__tests__/flows/quickQueries.ts @@ -7,11 +7,29 @@ export const quickQueries = () => describe("Quick queries to see states", () => { test("Quick queries to see states filler", () => expect(true).toBeTruthy()); - // test("Query cosmos.tx.v1beta1.getBlockWithTxs", async () => { - // const res = await queryClient.cosmos.tx.v1beta1.getTx({ - // hash: "C35404333376CD5FC1AFD57903061394F0333CF6B8047E9A693E0E59350AE695", + // test("Query ixo.bonds.v1beta1", async () => { + // const res = await queryClient.ixo.bonds.v1beta1.bondsDetailed(); + // console.log(res.bondsDetailed); + // expect(res).toBeTruthy(); + // }); + + // test("Query cosmos.tx.v1beta1.getTxsEvent", async () => { + // const res = await queryClient.cosmos.tx.v1beta1.getTxsEvent({ + // events: [`tx.height=${15955}`], + // orderBy: 1, // }); - // console.log(res.txResponse?.events); + // // console.log(res); + // console.log(res.txResponses[0]); + // console.log(createRegistry().decode(res.txResponses[0].tx!)); + // expect(res).toBeTruthy(); + // }); + + // test("Query cosmos.tx.v1beta1.getBlockByHeight", async () => { + // const res = + // await queryClient.cosmos.base.tendermint.v1beta1.getBlockByHeight({ + // height: Long.fromNumber(15955), + // }); + // console.log(res); // expect(res).toBeTruthy(); // }); @@ -68,12 +86,6 @@ export const quickQueries = () => // expect(res).toBeTruthy(); // }); - // test("query wasm store codes", async () => { - // const res = await queryClient.cosmwasm.wasm.v1.codes(); - // console.log(res.codeInfos); - // expect(res).toBeTruthy(); - // }); - // test("query tokens list by did", async () => { // const user = (await getUser(WalletUsers.tester).getAccounts())[0].address; // const res = await queryClient.ixo.token.v1beta1.tokenList({ @@ -109,6 +121,12 @@ export const quickQueries = () => // expect(res).toBeTruthy(); // }); + // test("query entity params", async () => { + // const res = await queryClient.ixo.entity.v1beta1.params(); + // console.log(res.params); + // expect(res).toBeTruthy(); + // }); + // test("query entity by id", async () => { // const res = await queryClient.ixo.entity.v1beta1.entity({ // id: "did:ixo:entity:eaff254f2fc62aefca0d831bc7361c14", diff --git a/__tests__/helpers/common.ts b/__tests__/helpers/common.ts index b08ccbed..2225ef9c 100644 --- a/__tests__/helpers/common.ts +++ b/__tests__/helpers/common.ts @@ -38,7 +38,7 @@ export type wallet = { export let wallets: { [key in WalletUsers]: wallet }; -export const generateWallets = async () => { +export const generateWallets = async (log = true) => { let generatedWallets = {}; for (const user of Object.values(WalletUsers)) { const mnemonics = utils.mnemonic.generateMnemonic(24); @@ -49,25 +49,27 @@ export const generateWallets = async () => { } wallets = generatedWallets as any; - // Logs wallet for tester to see account details for wallets - let walletLog = {}; - for (const [user, wallet] of Object.entries(wallets)) { - const edAccount = (await wallet.ed.getAccounts())[0]; - const secpAccount = (await wallet.secp.getAccounts())[0]; - walletLog[user] = { - ed: { - did: wallet.ed.did, - address: edAccount.address, - publicKey: base58.encode(edAccount.pubkey), - }, - secp: { - did: wallet.secp.did, - address: secpAccount.address, - publicKey: base58.encode(secpAccount.pubkey), - }, - }; + if (log) { + // Logs wallet for tester to see account details for wallets + let walletLog = {}; + for (const [user, wallet] of Object.entries(wallets)) { + const edAccount = (await wallet.ed.getAccounts())[0]; + const secpAccount = (await wallet.secp.getAccounts())[0]; + walletLog[user] = { + ed: { + did: wallet.ed.did, + address: edAccount.address, + publicKey: base58.encode(edAccount.pubkey), + }, + secp: { + did: wallet.secp.did, + address: secpAccount.address, + publicKey: base58.encode(secpAccount.pubkey), + }, + }; + } + console.log(walletLog); } - console.log(walletLog); }; export const generateNewWallet = async ( diff --git a/__tests__/index.spec.ts b/__tests__/index.spec.ts index 5b6dd8fd..5a8bbbd4 100644 --- a/__tests__/index.spec.ts +++ b/__tests__/index.spec.ts @@ -12,6 +12,7 @@ import { registerIids, registerIidsDev, generateBlockchainTestUsers, + iidAddEdKeys, } from "./flows/iids"; import { enititiesBasic, supamotoEntities } from "./flows/entities"; import { ibcBasic } from "./flows/ibc"; @@ -37,6 +38,7 @@ generateBlockchainTestUsers(); // registerIids(); // instantiateModulesProposals(); // iidsBasic(); +// iidAddEdKeys(); // bondsBasic(); // bondsSellsDisabled(); // bondsSellsEnabled(); diff --git a/__tests__/modules/CosmWasm.ts b/__tests__/modules/CosmWasm.ts index d80c0e82..a20d0e18 100644 --- a/__tests__/modules/CosmWasm.ts +++ b/__tests__/modules/CosmWasm.ts @@ -40,7 +40,11 @@ export const WasmStoreTrx = async ( return response; }; -export const WasmInstantiateTrx = async (codeId: number, msg: string) => { +export const WasmInstantiateTrx = async ( + codeId: number, + msg: string, + funds = 1 +) => { const client = await createClient(); const tester = getUser(); @@ -54,7 +58,7 @@ export const WasmInstantiateTrx = async (codeId: number, msg: string) => { codeId: Long.fromNumber(codeId), funds: [ cosmos.base.v1beta1.Coin.fromPartial({ - amount: "1", + amount: String(funds), denom: "uixo", }), ], diff --git a/__tests__/modules/Cosmos.ts b/__tests__/modules/Cosmos.ts index 4d8fd254..61dacd5e 100644 --- a/__tests__/modules/Cosmos.ts +++ b/__tests__/modules/Cosmos.ts @@ -43,8 +43,9 @@ export const BankSendTrx = async ( }), }; + // const response = await client.simulate(fromAddress, [message], undefined); const response = await client.signAndBroadcast(fromAddress, [message], fee); - return response; + return response as any; }; export const MsgSubmitProposalStoreCW = async ( @@ -75,7 +76,7 @@ export const MsgSubmitProposalStoreCW = async ( value: cosmwasm.wasm.v1.StoreCodeProposal.encode( cosmwasm.wasm.v1.StoreCodeProposal.fromPartial({ title: `Upload ${contract} smart contract`, - description: "Description", + description: "A cosmwasm smart contract", runAs: myAddress, wasmByteCode: new Uint8Array( getFileFromPath( diff --git a/__tests__/modules/Entity.ts b/__tests__/modules/Entity.ts index 498d6589..20aa7d5e 100644 --- a/__tests__/modules/Entity.ts +++ b/__tests__/modules/Entity.ts @@ -1,3 +1,4 @@ +import { cellNodeChainMapping } from "../../src/custom_queries/cellnode"; import { createAgentIidContext, createIidVerificationMethods, @@ -16,6 +17,7 @@ import { fee, keyType, WalletUsers } from "../helpers/constants"; export const CreateEntity = async ( entityType: string = "asset", context?: [{ key: string; val: string }], + relayerNodeDid = "", relayerNode: WalletUsers = WalletUsers.tester, signer: WalletUsers = WalletUsers.tester ) => { @@ -27,7 +29,7 @@ export const CreateEntity = async ( const myPubKey = account.pubkey; const did = tester.did; - const relayerNodeDid = getUser(relayerNode).did; + const relayerNodeDidLocal = relayerNodeDid || getUser(relayerNode).did; const message = { typeUrl: "/ixo.entity.v1beta1.MsgCreateEntity", @@ -44,7 +46,7 @@ export const CreateEntity = async ( controller: [did], ownerDid: did, ownerAddress: myAddress, - relayerNode: relayerNodeDid, + relayerNode: relayerNodeDidLocal, }), }; @@ -55,20 +57,23 @@ export const CreateEntity = async ( type CreateEntityAssetSupamotoParams = { inheritEntityDid: string; profile: string; - page: string; - creator: string; - administrator: string; + // page: string; + // creator: string; + // administrator: string; tags: string; claims: string; tokenMetadata: string; projectCert: string; - oracle: string; + oracles: string[]; + relayerDid?: string; }; export const CreateEntityAssetSupamoto = async ( p: CreateEntityAssetSupamotoParams ) => { const client = await createClient(); + const chainNetwork = "devnet"; + const tester = getUser(); const account = (await tester.getAccounts())[0]; const myAddress = account.address; @@ -93,9 +98,9 @@ export const CreateEntityAssetSupamoto = async ( }), service: [ ixo.iid.v1beta1.Service.fromPartial({ - id: "{id}#cellnode-pandora", + id: "{id}#cellnode", type: "cellnode", - serviceEndpoint: "https://devnet-cellnode.ixo.earth/", + serviceEndpoint: cellNodeChainMapping[chainNetwork], }), ixo.iid.v1beta1.Service.fromPartial({ id: "{id}#ixo", @@ -104,14 +109,14 @@ export const CreateEntityAssetSupamoto = async ( "https://github.com/cosmos/chain-registry/blob/master/ixo/chain.json?rpc/", }), ixo.iid.v1beta1.Service.fromPartial({ - id: "{id}#supamoto", + id: "{id}#emerging", type: "linkedDomains", - serviceEndpoint: "https://app.emerging.eco/collection/?id=", + serviceEndpoint: "https://app.emerging.eco", }), ixo.iid.v1beta1.Service.fromPartial({ - id: "{id}#dashboard", - type: "linkedDomains", - serviceEndpoint: "https://supamoto.jambo.earth/?id=", + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", }), ], linkedResource: [ @@ -120,47 +125,47 @@ export const CreateEntityAssetSupamoto = async ( type: "Settings", description: "Profile", mediaType: "application/ld+json", - serviceEndpoint: p.profile, - proof: p.profile.split(".")[0].split("/")[2], - encrypted: "false", - right: "", - }), - ixo.iid.v1beta1.LinkedResource.fromPartial({ - id: "{id}#page", - type: "Settings", - description: "Page", - mediaType: "application/ld+json", - serviceEndpoint: `#cellnode-pandora/public/${p.page}`, - proof: p.page, - encrypted: "false", - right: "", - }), - ixo.iid.v1beta1.LinkedResource.fromPartial({ - id: "{id}#creator", - type: "verifiableCredential", - description: "Creator", - mediaType: "application/ld+json", - serviceEndpoint: `#cellnode-pandora/public/${p.creator}`, - proof: p.creator, - encrypted: "false", - right: "", - }), - ixo.iid.v1beta1.LinkedResource.fromPartial({ - id: "{id}#administrator", - type: "VerifiableCredential", - description: "Administrator", - mediaType: "application/ld+json", - serviceEndpoint: `#cellnode-pandora/public/${p.administrator}`, - proof: p.administrator, + serviceEndpoint: `cellnode:/public/${p.profile}`, + proof: p.profile, encrypted: "false", right: "", }), + // ixo.iid.v1beta1.LinkedResource.fromPartial({ + // id: "{id}#page", + // type: "Settings", + // description: "Page", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${p.page}`, + // proof: p.page, + // encrypted: "false", + // right: "", + // }), + // ixo.iid.v1beta1.LinkedResource.fromPartial({ + // id: "{id}#creator", + // type: "verifiableCredential", + // description: "Creator", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${p.creator}`, + // proof: p.creator, + // encrypted: "false", + // right: "", + // }), + // ixo.iid.v1beta1.LinkedResource.fromPartial({ + // id: "{id}#administrator", + // type: "VerifiableCredential", + // description: "Administrator", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${p.administrator}`, + // proof: p.administrator, + // encrypted: "false", + // right: "", + // }), ixo.iid.v1beta1.LinkedResource.fromPartial({ id: "{id}#tags", type: "Settings", description: "Tags", mediaType: "application/ld+json", - serviceEndpoint: `#cellnode-pandora/public/${p.tags}`, + serviceEndpoint: `cellnode:/public/${p.tags}`, proof: p.tags, encrypted: "false", right: "", @@ -170,7 +175,7 @@ export const CreateEntityAssetSupamoto = async ( type: "Settings", description: "Claims", mediaType: "application/ld+json", - serviceEndpoint: `#cellnode-pandora/public/${p.claims}`, + serviceEndpoint: `cellnode:/public/${p.claims}`, proof: p.claims, encrypted: "false", right: "", @@ -180,8 +185,8 @@ export const CreateEntityAssetSupamoto = async ( type: "TokenMetadata", description: "Impact Token", mediaType: "application/json", - serviceEndpoint: p.tokenMetadata, - proof: p.tokenMetadata.split(".")[0].split("/")[2], + serviceEndpoint: `ipfs:${p.tokenMetadata}`, + proof: p.tokenMetadata, encrypted: "false", right: "", }), @@ -190,8 +195,8 @@ export const CreateEntityAssetSupamoto = async ( type: "VerifiableCredential", description: "Project Certificate", mediaType: "application/ld+json", - serviceEndpoint: p.projectCert, - proof: p.projectCert.split(".")[0].split("/")[2], + serviceEndpoint: `ipfs:${p.projectCert}`, + proof: p.projectCert, encrypted: "false", right: "", }), @@ -200,17 +205,7 @@ export const CreateEntityAssetSupamoto = async ( type: "WebDashboard", description: "Collection Dashboard", mediaType: "application/html", - serviceEndpoint: "#dashboard-collection", - proof: "", - encrypted: "false", - right: "#apitoken", - }), - ixo.iid.v1beta1.LinkedResource.fromPartial({ - id: "{id}#asset-dashboard", - type: "WebDashboard", - description: "SupaMoto Dashboard", - mediaType: "application/html", - serviceEndpoint: "#dashboard-supamoto", + serviceEndpoint: "emerging", proof: "", encrypted: "false", right: "#apitoken", @@ -219,17 +214,17 @@ export const CreateEntityAssetSupamoto = async ( accordedRight: [ ixo.iid.v1beta1.AccordedRight.fromPartial({ id: "{id}#mintNFT", - type: "capability/mint", - mechanism: "cw721", - message: "msgMintNFT", + type: "capability/createEntity", + mechanism: "x/entity", + message: "MsgCreateEntity", service: "#ixo", }), ixo.iid.v1beta1.AccordedRight.fromPartial({ id: "{id}#carbon-claim", type: "capability/attest", mechanism: "x/claims", - message: "msgSubmitClaim", - service: "#cellnode", + message: "MsgSubmitClaim", + service: "#ixo", }), ixo.iid.v1beta1.AccordedRight.fromPartial({ id: "{id}#legal", @@ -241,18 +236,31 @@ export const CreateEntityAssetSupamoto = async ( type: "AccessToken", mechanism: "authentication", }), + ixo.iid.v1beta1.AccordedRight.fromPartial({ + id: "{id}#view", + type: "capability/access", + mechanism: "zcap", + service: "emerging", + }), + ixo.iid.v1beta1.AccordedRight.fromPartial({ + id: "{id}#mintCARBON", + type: "capability/mintToken", + mechanism: "x/token", + message: "MsgMintToken", + service: "ixo", + }), ], - linkedEntity: [ + linkedEntity: p.oracles.map((o) => ixo.iid.v1beta1.LinkedEntity.fromPartial({ - id: p.oracle, + id: o, type: "oracle", relationship: "verifies", - service: "", - }), - ], + service: "ixo", + }) + ), ownerDid: did, ownerAddress: myAddress, - relayerNode: did, + relayerNode: p.relayerDid || did, }), }; @@ -262,9 +270,10 @@ export const CreateEntityAssetSupamoto = async ( export const CreateEntityAssetSupamotoInstance = async ( inheritEntityDid: string, - deviceId: string, + deviceId: string | number, index: number, - deviceCreds: string + deviceCreds: string, + relayerDid?: string ) => { const client = await createClient(); @@ -277,7 +286,7 @@ export const CreateEntityAssetSupamotoInstance = async ( const message = { typeUrl: "/ixo.entity.v1beta1.MsgCreateEntity", value: ixo.entity.v1beta1.MsgCreateEntity.fromPartial({ - entityType: "asset", + entityType: "asset/device", entityStatus: 0, context: createAgentIidContext([{ key: "class", val: inheritEntityDid }]), controller: [did], @@ -292,12 +301,12 @@ export const CreateEntityAssetSupamotoInstance = async ( alsoKnownAs: `{id}#${index}`, linkedResource: [ ixo.iid.v1beta1.LinkedResource.fromPartial({ - id: "{entity}#device-credential", + id: "{id}#device-credential", type: "VerifiableCredential", description: "Certificate of Manufacture", mediaType: "application/ld+json", - serviceEndpoint: deviceCreds, - proof: deviceCreds.split(".")[0].split("/")[2], + serviceEndpoint: `ipfs:${deviceCreds}`, + proof: deviceCreds, encrypted: "false", right: "", }), @@ -306,30 +315,24 @@ export const CreateEntityAssetSupamotoInstance = async ( type: "WebDashboard", description: "SupaMoto Dashboard", mediaType: "application/html", - serviceEndpoint: `dashboard-supamoto:${deviceId}`, + serviceEndpoint: `emerging:/collection/?id=${deviceId}`, proof: "", encrypted: "false", right: "#apitoken", }), ], - accordedRight: [ - ixo.iid.v1beta1.AccordedRight.fromPartial({ - id: "{did}#view", - type: "capability/access", - mechanism: "zcap", - service: "", - }), - ], + accordedRight: [], linkedEntity: [ ixo.iid.v1beta1.LinkedEntity.fromPartial({ - id: "", - type: "", - relationship: "", + id: inheritEntityDid, + type: "asset/collection", + relationship: "affordance", + service: "ixo", }), ], ownerDid: did, ownerAddress: myAddress, - relayerNode: did, + relayerNode: relayerDid || did, }), }; diff --git a/__tests__/modules/Iid.ts b/__tests__/modules/Iid.ts index 7d7a0870..cf5bbe17 100644 --- a/__tests__/modules/Iid.ts +++ b/__tests__/modules/Iid.ts @@ -134,7 +134,7 @@ export const DeleteIidContext = async () => { * @param relationships list with values: 'authentication' | 'assertionMethod' | 'keyAgreement' | 'capabilityInvocation' | 'capabilityDelegation' */ export const AddVerification = async ( - relationships: string[] = ["authentication"] + relationships: string[] = ["authentication", "assertionMethod"] ) => { const client = await createClient(); @@ -143,8 +143,8 @@ export const AddVerification = async ( const myAddress = account.address; const did = tester.did; - const alice = getUser(WalletUsers.alice); - const aliceAccount = (await alice.getAccounts())[0]; + const accountEd = (await getUser(WalletUsers.tester, "ed").getAccounts())[0]; + const myPubkey = accountEd.pubkey; const message = { typeUrl: "/ixo.iid.v1beta1.MsgAddVerification", @@ -153,10 +153,10 @@ export const AddVerification = async ( verification: ixo.iid.v1beta1.Verification.fromPartial({ relationships: relationships, method: customMessages.iid.createVerificationMethod( - alice.did, - aliceAccount.pubkey, - alice.did, - keyType + did, + myPubkey, + did, + "ed" ), }), signer: myAddress, @@ -171,7 +171,7 @@ export const AddVerification = async ( * @param relationships list with values: 'authentication' | 'assertionMethod' | 'keyAgreement' | 'capabilityInvocation' | 'capabilityDelegation' */ export const SetVerificationRelationships = async ( - relationships: string[] = ["authentication"] + relationships: string[] = ["assertionMethod"] ) => { const client = await createClient(); diff --git a/__tests__/modules/Token.ts b/__tests__/modules/Token.ts index 189b9783..33805638 100644 --- a/__tests__/modules/Token.ts +++ b/__tests__/modules/Token.ts @@ -216,7 +216,7 @@ export const MsgGrantContract = async ( grantee: granteeAddress, }); const mintAuth = granteeGrants.grants.find( - (g) => g.authorization?.typeUrl == "/ixo.token.v1beta1.MsgMintToken" + (g) => g.authorization?.typeUrl == "/ixo.token.v1beta1.MintAuthorization" ); const granteeCurrentAuthConstraints = overrideCurretGrants || mintAuth == undefined diff --git a/__tests__/setup/Entity.ts b/__tests__/setup/Entity.ts new file mode 100644 index 00000000..23f197cf --- /dev/null +++ b/__tests__/setup/Entity.ts @@ -0,0 +1,178 @@ +import { + createAgentIidContext, + createIidVerificationMethods, +} from "../../src/messages/iid"; +import { createClient, getUser, ixo } from "../helpers/common"; +import { fee, keyType, WalletUsers } from "../helpers/constants"; +import { SetupDaoConstantFields } from "./impacts/constants"; +import { SetupClassConstants } from "./classes/constants"; +import { LinkedResourcesUploaded } from "./constants"; +import base58 from "bs58"; + +export const CreateEntityBasic = async ( + entity: SetupClassConstants["dao"], + signer: WalletUsers = WalletUsers.tester +) => { + const client = await createClient(getUser(signer)); + + const tester = getUser(signer); + const account = (await tester.getAccounts())[0]; + const myAddress = account.address; + const myPubKey = account.pubkey; + const did = tester.did; + + const context = !entity.contextClass + ? createAgentIidContext() + : createAgentIidContext([{ key: "class", val: entity.contextClass }]); + + const message = { + typeUrl: "/ixo.entity.v1beta1.MsgCreateEntity", + value: ixo.entity.v1beta1.MsgCreateEntity.fromPartial({ + entityType: entity.entityType, + context: context, + verification: createIidVerificationMethods({ + did, + pubkey: myPubKey, + address: myAddress, + controller: did, + type: keyType, + }), + controller: [did], + ownerDid: did, + ownerAddress: myAddress, + relayerNode: entity.relayerNode || did, + }), + }; + + const response = await client.signAndBroadcast(myAddress, [message], fee); + return response; +}; + +export const CreateEntity = async ( + entity: SetupDaoConstantFields["entity"], + linkedResourcesUploaded: LinkedResourcesUploaded, + addEdKeys = false +) => { + const client = await createClient(); + + const tester = getUser(); + const account = (await tester.getAccounts())[0]; + const myPubKey = account.pubkey; + const myAddress = account.address; + const did = tester.did; + + const linkedResources = linkedResourcesUploaded.map( + ({ name, cid, type, storage }) => + ixo.iid.v1beta1.LinkedResource.fromPartial({ + id: `{id}#${name}`, + type, + description: name.slice(0, 1).toLocaleUpperCase() + name.slice(1), + mediaType: "application/ld+json", + serviceEndpoint: + storage === "cellnode" ? `cellnode:/public/${cid}` : `ipfs:${cid}`, + proof: cid, + encrypted: "false", + right: "", + }) + ); + + const context = !entity.contextClass + ? createAgentIidContext() + : createAgentIidContext([{ key: "class", val: entity.contextClass }]); + + const verification = createIidVerificationMethods({ + did, + pubkey: myPubKey, + address: myAddress, + controller: did, + type: keyType, + }); + + // Add ed keys user to verification method for verification of credentials + if (addEdKeys) { + const edPubKey = (await getUser(WalletUsers.alice).getAccounts())[0].pubkey; + const pubkeyBase58 = base58.encode(edPubKey); + + verification.push( + ixo.iid.v1beta1.Verification.fromPartial({ + relationships: ["attestation"], + method: ixo.iid.v1beta1.VerificationMethod.fromPartial({ + id: did + "#" + pubkeyBase58, + type: "Ed25519VerificationKey2018", + publicKeyBase58: pubkeyBase58, + controller: "{id}", + }), + }) + ); + } + + const message = { + typeUrl: "/ixo.entity.v1beta1.MsgCreateEntity", + value: ixo.entity.v1beta1.MsgCreateEntity.fromPartial({ + entityType: entity.entityType, + entityStatus: 0, + controller: [did], + context, + alsoKnownAs: entity.alsoKnownAs, + service: entity.service.map((s) => + ixo.iid.v1beta1.Service.fromPartial(s) + ), + // verification: entity.verification.map((v) => + // ixo.iid.v1beta1.Verification.fromPartial({ + // relationships: v.relationships, + // method: ixo.iid.v1beta1.VerificationMethod.fromPartial(v.method), + // }) + // ), + // since no groups at time of run adding creators keys as verification methods + verification: verification, + linkedResource: linkedResources.concat( + entity.linkedResources.map((r) => + ixo.iid.v1beta1.LinkedResource.fromPartial(r) + ) + ), + accordedRight: [], + // linkedEntity: entity.groupAddresses.map((address) => + // ixo.iid.v1beta1.LinkedEntity.fromPartial({ + // id: `{id}#${address}`, + // type: "Group", + // relationship: "subsidiary", + // service: "", + // }) + // ), + // since no groups at time of run no linkedEntities + linkedEntity: [], + ownerDid: did, + ownerAddress: myAddress, + relayerNode: entity.relayerNode || did, + }), + }; + + const response = await client.signAndBroadcast(myAddress, [message], fee); + return response; +}; + +export const TransferEntity = async ( + entityDid: string, + recipientDid: string, + signer: WalletUsers = WalletUsers.tester +) => { + const client = await createClient(getUser(signer)); + + const tester = getUser(signer); + const account = (await tester.getAccounts())[0]; + const myAddress = account.address; + const did = tester.did; + + const message = { + typeUrl: "/ixo.entity.v1beta1.MsgTransferEntity", + value: ixo.entity.v1beta1.MsgTransferEntity.fromPartial({ + id: entityDid, + ownerDid: did, + ownerAddress: myAddress, + recipientDid, + }), + }; + + const response = await client.signAndBroadcast(myAddress, [message], fee); + return response; +}; diff --git a/__tests__/setup/Groups.ts b/__tests__/setup/Groups.ts new file mode 100644 index 00000000..c86a61b0 --- /dev/null +++ b/__tests__/setup/Groups.ts @@ -0,0 +1,99 @@ +import { customQueries, utils } from "../helpers/common"; +import { + ChainNetwork, + SetupGroupConstantKeys, + setup_group_constants, +} from "./impacts/constants"; + +export const createGroupMsg = ( + chainNetwork: ChainNetwork, + groupFromConstants: SetupGroupConstantKeys +) => { + const daoProposalContractCode = customQueries.contract.getContractCode( + chainNetwork, + "dao_proposal_single" + ); + const daoPreProposalContractCode = customQueries.contract.getContractCode( + chainNetwork, + "dao_pre_propose_single" + ); + const daoVotingCw4ContractCode = customQueries.contract.getContractCode( + chainNetwork, + "dao_voting_cw4" + ); + const cw4ContractCode = customQueries.contract.getContractCode( + chainNetwork, + "cw4_group" + ); + const daoVotingCw20StakedContractCode = + customQueries.contract.getContractCode( + chainNetwork, + "dao_voting_cw20_staked" + ); + const cw20BaseContractCode = customQueries.contract.getContractCode( + chainNetwork, + "cw20_base" + ); + const cw20StakeContractCode = customQueries.contract.getContractCode( + chainNetwork, + "cw20_stake" + ); + + const groupConst = setup_group_constants({ + daoVotingCw4ContractCode, + daoVotingCw20StakedContractCode, + cw4ContractCode, + cw20BaseContractCode, + cw20StakeContractCode, + })[groupFromConstants]; + const gProposal = groupConst.proposal_modules_instantiate_info; + const gVoting = groupConst.voting_module_instantiate_info; + + const msg = { + admin: null, + automatically_add_cw20s: true, + automatically_add_cw721s: true, + description: groupConst.description, + image_url: groupConst.image_url, + name: groupConst.name, + proposal_modules_instantiate_info: [ + { + admin: { core_module: {} }, + code_id: daoProposalContractCode, + label: `${groupConst.name} Dao_DaoProposalSingle`, + msg: utils.conversions.jsonToBase64({ + allow_revoting: gProposal.allow_revoting, + close_proposal_on_execution_failure: + gProposal.close_proposal_on_execution_failure, + max_voting_period: gProposal.max_voting_period, + min_voting_period: gProposal.min_voting_period, + only_members_execute: gProposal.only_members_execute, + pre_propose_info: { + module_may_propose: { + info: { + admin: { core_module: {} }, + code_id: daoPreProposalContractCode, + label: `${groupConst.name} Dao_pre-propose-DaoProposalSingle`, + msg: utils.conversions.jsonToBase64({ + deposit_info: gProposal.pre_propose_info.deposit_info, + extension: {}, + open_proposal_submission: + gProposal.pre_propose_info.open_proposal_submission, + }), + }, + }, + }, + threshold: gProposal.threshold, + }), + }, + ], + voting_module_instantiate_info: { + admin: { core_module: {} }, + code_id: gVoting.code_id, + label: `${groupConst.name} Dao_Voting_module`, + msg: utils.conversions.jsonToBase64(gVoting.msg), + }, + }; + + return msg; +}; diff --git a/__tests__/setup/Iid.ts b/__tests__/setup/Iid.ts new file mode 100644 index 00000000..aaf8010d --- /dev/null +++ b/__tests__/setup/Iid.ts @@ -0,0 +1,46 @@ +import { createAgentIidContext } from "../../src/messages/iid"; +import { createClient, getUser, ixo, utils } from "../helpers/common"; +import { fee, WalletUsers } from "../helpers/constants"; + +export const CreateIidDocForGroup = async ( + address: string, + signer: WalletUsers = WalletUsers.tester +) => { + const client = await createClient(getUser(signer)); + const signerAddress = (await getUser(signer).getAccounts())[0].address; + const did = utils.did.generateCosmwasmDid(address); + + const message = { + typeUrl: "/ixo.iid.v1beta1.MsgCreateIidDocument", + value: ixo.iid.v1beta1.MsgCreateIidDocument.fromPartial({ + context: createAgentIidContext(), + id: did, + alsoKnownAs: "group", + verifications: [ + ixo.iid.v1beta1.Verification.fromPartial({ + relationships: ["authentication"], + method: ixo.iid.v1beta1.VerificationMethod.fromPartial({ + id: did, + type: "CosmosAccountAddress", + blockchainAccountID: address, + controller: "{id}", + }), + }), + ixo.iid.v1beta1.Verification.fromPartial({ + relationships: ["authentication"], + method: ixo.iid.v1beta1.VerificationMethod.fromPartial({ + id: did + "#" + address, + type: "CosmosAccountAddress", + blockchainAccountID: address, + controller: "{id}", + }), + }), + ], + signer: signerAddress, + controllers: [did], + }), + }; + + const response = await client.signAndBroadcast(signerAddress, [message], fee); + return response; +}; diff --git a/__tests__/setup/classes/constants.ts b/__tests__/setup/classes/constants.ts new file mode 100644 index 00000000..7beb74a2 --- /dev/null +++ b/__tests__/setup/classes/constants.ts @@ -0,0 +1,25 @@ +export const setup_class_constants = { + dao: { + entityType: "dao", + relayerNode: undefined, + contextClass: "", + }, + asset: { + entityType: "asset", + relayerNode: undefined, + contextClass: "", + }, + oracle: { + entityType: "oracle", + relayerNode: undefined, + contextClass: "", + }, + protocol: { + entityType: "protocol", + relayerNode: undefined, + contextClass: "", + }, +}; + +// Types for typescript strict type checking, please ignore +export type SetupClassConstants = typeof setup_class_constants; diff --git a/__tests__/setup/classes/setupFlow.ts b/__tests__/setup/classes/setupFlow.ts new file mode 100644 index 00000000..7456e33a --- /dev/null +++ b/__tests__/setup/classes/setupFlow.ts @@ -0,0 +1,48 @@ +import { + generateNewWallet, + sendFromFaucet, + testMsg, + utils, +} from "../../helpers/common"; +import { WalletUsers } from "../../helpers/constants"; +import * as IidMain from "../../modules/Iid"; +import { setup_class_constants } from "./constants"; +import * as Entity from "../Entity"; +import { chainNetwork } from "../index.setup.spec"; + +export const classesFlow = () => + describe("Flow for creating classes", () => { + // =============================================================== + // Set Testers mnemonic to env variable and ledger root user did + // =============================================================== + + // below test can fail as user might already be ledgered, that is ok + beforeAll(() => + generateNewWallet(WalletUsers.tester, process.env.TESTER_MNEMONIC) + ); + + // @ts-ignore + if (chainNetwork != "mainnet") { + // Send from faucet for devnet/testnet + sendFromFaucet(WalletUsers.tester); + } + testMsg("/ixo.iid.v1beta1.MsgCreateIidDocument", () => + IidMain.CreateIidDoc(WalletUsers.tester) + ); + + // =============================================================== + // Create Entities + // =============================================================== + // Creating the parent classes here that will be in context of all following entities + + testMsg("/ixo.entity.v1beta1.MsgCreateEntity classes", async () => { + for (const c of Object.keys(setup_class_constants)) { + const res = await Entity.CreateEntityBasic(setup_class_constants[c]); + if (res.code != 0) throw new Error(res.rawLog); + const did = utils.common.getValueFromEvents(res, "wasm", "token_id"); + console.log({ [c]: did }); + } + + return true as any; + }); + }); diff --git a/__tests__/setup/constants.ts b/__tests__/setup/constants.ts new file mode 100644 index 00000000..df7675ba --- /dev/null +++ b/__tests__/setup/constants.ts @@ -0,0 +1,18 @@ +export const dids = { + daoClass: "", + oracleClass: "", + protocolClass: "", + assetClass: "", + impactsDao: "", + emergingDao: "", + cookstoveAssetProtocol: "", + prospectOracle: "", + scalnyxOracle: "", +}; + +export type LinkedResourcesUploaded = { + name: string; + cid: string; + type: string; + storage: "cellnode" | "ipfs"; +}[]; diff --git a/__tests__/setup/ecs/constants.ts b/__tests__/setup/ecs/constants.ts new file mode 100644 index 00000000..85bc1b3e --- /dev/null +++ b/__tests__/setup/ecs/constants.ts @@ -0,0 +1,146 @@ +import { cellNodeChainMapping } from "../../../src/custom_queries/cellnode"; +import { dids } from "../constants"; +import { chainNetwork } from "../index.setup.spec"; + +export const setup_dao_constants = () => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "dao", + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: dids.impactsDao, + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: dids.daoClass, + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "The Impact DAO cooperative makes outcomes-based investments into innovations, projects and ventures that can dleiver Internet of Impact solutions. Members of the DAO are pioneering innovators, investors, builders, and implementors who contribute capital, work, open-source software, and market access opportunities. The DAO treasury provides financing for the ecosystem by growing a portfolio of assets and by generating revenues from its investments. The DAO Tokens represent each member's participation share in the treasury that can be exchanged after the DAO breaks even. More recent investors recive a liquidation preference.", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Market Relayer"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "Impact DAO 1", + image: + "https://thumbs.dreamstime.com/b/environment-earth-day-hands-trees-growing-seedlings-bokeh-green-background-female-hand-holding-tree-nature-field-gra-130247647.jpg", + logo: "logoLink", + brand: "Impact DAO", + location: "Global", + description: + "The Impact DAO cooperative consists of participants who are building the Internet of Impact to address sustainable development, human security, energy transitions, and ecological regeneration..", + attributes: [ + { + key: "Model", + value: "MimiMoto", + }, + { + key: "Location", + value: "Global", + }, + { + key: "Usage", + value: "Global", + }, + { + key: "Product", + value: "Impact DAO tokens", + }, + ], + metrics: [ + { + prefix: "$IMPACT", + metric: "Token Price", + suffix: "", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +// Types for typescript strict type checking, please ignore +export type SetupDaoConstantFields = ReturnType; diff --git a/__tests__/setup/ecs/setupFlow.ts b/__tests__/setup/ecs/setupFlow.ts new file mode 100644 index 00000000..c59d2e67 --- /dev/null +++ b/__tests__/setup/ecs/setupFlow.ts @@ -0,0 +1,99 @@ +import { + customQueries, + generateNewWallet, + sendFromFaucet, + testMsg, + utils, +} from "../../helpers/common"; +import { WalletUsers } from "../../helpers/constants"; +import * as IidMain from "../../modules/Iid"; +import { setup_dao_constants } from "./constants"; +import * as Entity from "../Entity"; +import { chainNetwork } from "../index.setup.spec"; +import { LinkedResourcesUploaded } from "../constants"; + +export const ecsFlow = () => + describe("Flow for creating a Entity (dao/protocol/oracle)", () => { + // =============================================================== + // Set Testers mnemonic to env variable and ledger root user did + // =============================================================== + + // below test can fail as user might already be ledgered, that is ok + beforeAll(() => + generateNewWallet(WalletUsers.tester, process.env.TESTER_MNEMONIC) + ); + + // @ts-ignore + if (chainNetwork != "mainnet") { + // Send from faucet for devnet/testnet + sendFromFaucet(WalletUsers.tester); + } + testMsg("/ixo.iid.v1beta1.MsgCreateIidDocument", () => + IidMain.CreateIidDoc(WalletUsers.tester) + ); + + // =============================================================== + // Create Entities + // =============================================================== + // You can create all your entities below, you can just copy a whole entity creation and make + // as many as you want, just ensure you have all the groups needed that will be used and that for each + // entity there is a corresponding exported setup_{name}_constants that you can use for the entity + + // =============================== START + let daoDid: string; + let adminAccount: string; + let linkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_dao_constants(); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ linkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + linkedResourcesUploaded + ); + daoDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + adminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ daoDid, adminAccount }); + + return res; + }); + // =============================== END + }); diff --git a/__tests__/setup/emerging/constants.ts b/__tests__/setup/emerging/constants.ts new file mode 100644 index 00000000..086f1fb2 --- /dev/null +++ b/__tests__/setup/emerging/constants.ts @@ -0,0 +1,550 @@ +import { cellNodeChainMapping } from "../../../src/custom_queries/cellnode"; +import { dids } from "../constants"; +import { chainNetwork } from "../index.setup.spec"; + +export const setup_dao_constants = () => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "dao", + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: dids.impactsDao, + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: dids.daoClass, + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "The Emerging Eco DAO constitutes of stakeholders who are particpating in the transition to IoT-integrated clean cook stoves, and who are supporting regenerative household transitions.", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Market Relayer", "Rights"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "Emerging Eco", + image: "imageLink", + logo: "logoLink", + brand: "Emerging Eco", + location: "Zambia", + description: ".", + attributes: [ + { + key: "Usage", + value: "Domestic", + }, + { + key: "Product", + value: "SupaMoto credit tokens", + }, + ], + metrics: [ + { + prefix: "USD", + metric: "Token Price", + suffix: "Average/NFT", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Credits", + metric: "CARBON", + suffix: "/month (moving average)", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +export const setup_protocol_ver_claims_constants = () => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "protocol/claims", + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: dids.emergingDao, + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: dids.protocolClass, + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "The Emerging Eco DAO constitutes of stakeholders who are particpating in the transition to IoT-integrated clean cook stoves, and who are supporting regenerative household transitions.", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Market Relayer", "Rights"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "Emerging Eco", + image: "imageLink", + logo: "logoLink", + brand: "Emerging Eco", + location: "Zambia", + description: ".", + attributes: [ + { + key: "Usage", + value: "Domestic", + }, + { + key: "Product", + value: "SupaMoto credit tokens", + }, + ], + metrics: [ + { + prefix: "USD", + metric: "Token Price", + suffix: "Average/NFT", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Credits", + metric: "CARBON", + suffix: "/month (moving average)", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +export const setup_protocol_cooking_constants = () => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "protocol/claims", + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: dids.emergingDao, + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: dids.protocolClass, + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "The Emerging Eco DAO constitutes of stakeholders who are particpating in the transition to IoT-integrated clean cook stoves, and who are supporting regenerative household transitions.", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Market Relayer", "Rights"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "Emerging Eco", + image: "imageLink", + logo: "logoLink", + brand: "Emerging Eco", + location: "Zambia", + description: ".", + attributes: [ + { + key: "Usage", + value: "Domestic", + }, + { + key: "Product", + value: "SupaMoto credit tokens", + }, + ], + metrics: [ + { + prefix: "USD", + metric: "Token Price", + suffix: "Average/NFT", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Credits", + metric: "CARBON", + suffix: "/month (moving average)", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +export const setup_protocol_fuel_constants = () => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "protocol/claims", + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: dids.emergingDao, + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: dids.protocolClass, + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "The Emerging Eco DAO constitutes of stakeholders who are particpating in the transition to IoT-integrated clean cook stoves, and who are supporting regenerative household transitions.", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Market Relayer", "Rights"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "Emerging Eco", + image: "imageLink", + logo: "logoLink", + brand: "Emerging Eco", + location: "Zambia", + description: ".", + attributes: [ + { + key: "Usage", + value: "Domestic", + }, + { + key: "Product", + value: "SupaMoto credit tokens", + }, + ], + metrics: [ + { + prefix: "USD", + metric: "Token Price", + suffix: "Average/NFT", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Credits", + metric: "CARBON", + suffix: "/month (moving average)", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +// Types for typescript strict type checking, please ignore +export type SetupDaoConstantFields = ReturnType; diff --git a/__tests__/setup/emerging/setupFlow.ts b/__tests__/setup/emerging/setupFlow.ts new file mode 100644 index 00000000..7d591079 --- /dev/null +++ b/__tests__/setup/emerging/setupFlow.ts @@ -0,0 +1,332 @@ +import { + customQueries, + generateNewWallet, + sendFromFaucet, + testMsg, + utils, +} from "../../helpers/common"; +import { WalletUsers } from "../../helpers/constants"; +import * as IidMain from "../../modules/Iid"; +import { + setup_dao_constants, + setup_protocol_cooking_constants, + setup_protocol_fuel_constants, + setup_protocol_ver_claims_constants, +} from "./constants"; +import * as Entity from "../Entity"; +import * as Entity1 from "../../modules/Entity"; +import { chainNetwork } from "../index.setup.spec"; +import { LinkedResourcesUploaded, dids } from "../constants"; + +export const emergingDaoFlow = () => + describe("Flow for creating a Entity (dao/protocol/oracle)", () => { + // =============================================================== + // Set Testers mnemonic to env variable and ledger root user did + // =============================================================== + + // below test can fail as user might already be ledgered, that is ok + beforeAll(() => + generateNewWallet(WalletUsers.tester, process.env.TESTER_MNEMONIC) + ); + + // @ts-ignore + if (chainNetwork != "mainnet") { + // Send from faucet for devnet/testnet + sendFromFaucet(WalletUsers.tester); + } + testMsg("/ixo.iid.v1beta1.MsgCreateIidDocument", () => + IidMain.CreateIidDoc(WalletUsers.tester) + ); + + // =============================================================== + // Create Entities + // =============================================================== + // You can create all your entities below, you can just copy a whole entity creation and make + // as many as you want, just ensure you have all the groups needed that will be used and that for each + // entity there is a corresponding exported setup_{name}_constants that you can use for the entity + + // =============================== START + let daoDid: string; + let adminAccount: string; + let linkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_dao_constants(); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ linkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + linkedResourcesUploaded + ); + daoDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + adminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ daoDid, adminAccount }); + + return res; + }); + // =============================== END + }); + +export const emergingProtocolsFlow = () => + describe("Flow for creating a Entity (dao/protocol/oracle)", () => { + // =============================================================== + // Set Testers mnemonic to env variable and ledger root user did + // =============================================================== + + // below test can fail as user might already be ledgered, that is ok + beforeAll(() => + Promise.all([ + generateNewWallet(WalletUsers.tester, process.env.TESTER_MNEMONIC), + generateNewWallet(WalletUsers.alice, process.env.ED_KEYS_MNEMONIC), + ]) + ); + + // @ts-ignore + if (chainNetwork != "mainnet") { + // Send from faucet for devnet/testnet + sendFromFaucet(WalletUsers.tester); + } + testMsg("/ixo.iid.v1beta1.MsgCreateIidDocument", () => + IidMain.CreateIidDoc(WalletUsers.tester) + ); + + // =============================================================== + // Create Entities + // =============================================================== + // You can create all your entities below, you can just copy a whole entity creation and make + // as many as you want, just ensure you have all the groups needed that will be used and that for each + // entity there is a corresponding exported setup_{name}_constants that you can use for the entity + + // =============================== START + let protVerClaimsDid: string; + let protVerClaimsAdminAccount: string; + let protVerClaimsLinkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_protocol_ver_claims_constants(); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + protVerClaimsLinkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + protVerClaimsLinkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ protVerClaimsLinkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + protVerClaimsLinkedResourcesUploaded + ); + protVerClaimsDid = utils.common.getValueFromEvents( + res, + "wasm", + "token_id" + ); + protVerClaimsAdminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ protVerClaimsDid, protVerClaimsAdminAccount }); + + return res; + }); + // =============================== END + + // =============================== START + let protCookingDid: string; + let protCookingAdminAccount: string; + let protCookingLinkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_protocol_cooking_constants(); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + protCookingLinkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + protCookingLinkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ protCookingLinkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + protCookingLinkedResourcesUploaded + ); + protCookingDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + protCookingAdminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ protCookingDid, protCookingAdminAccount }); + + return res; + }); + // =============================== END + + // =============================== START + let protFuelDid: string; + let protFuelAdminAccount: string; + let protFuelLinkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_protocol_fuel_constants(); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + protFuelLinkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + protFuelLinkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ protFuelLinkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + protFuelLinkedResourcesUploaded + ); + protFuelDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + protFuelAdminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ protFuelDid, protFuelAdminAccount }); + + return res; + }); + // =============================== END + + // Create cookstove-asset-protocol + // ========================================= + let cookstoveAssetProtocolDid: string; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity protocol", async () => { + const res = await Entity1.CreateEntity( + "protocol/asset", + [{ key: "class", val: dids.protocolClass }], + dids.emergingDao + ); + cookstoveAssetProtocolDid = utils.common.getValueFromEvents( + res, + "wasm", + "token_id" + ); + console.log({ cookstoveAssetProtocolDid }); + return res; + }); + }); diff --git a/__tests__/setup/fullExample/constants.ts b/__tests__/setup/fullExample/constants.ts new file mode 100644 index 00000000..5ebd4051 --- /dev/null +++ b/__tests__/setup/fullExample/constants.ts @@ -0,0 +1,421 @@ +import { cellNodeChainMapping } from "../../../src/custom_queries/cellnode"; +import { dids } from "../constants"; + +export const chainNetwork: ChainNetwork = "devnet"; + +// You can define your group constants here, to create more than one group +// you can just copy the whole management_group field and make another one +// for example members_group, oracle_group, yarn start + +export const setup_group_constants = ({ + daoVotingCw4ContractCode, + daoVotingCw20StakedContractCode, + cw4ContractCode, + cw20BaseContractCode, + cw20StakeContractCode, +}) => ({ + management_group: { + name: "Management", + description: "Management group for admin related management", + image_url: + "https://sienaconstruction.com/wp-content/uploads/2017/05/test-image.jpg", + proposal_modules_instantiate_info: { + allow_revoting: false, + close_proposal_on_execution_failure: true, + max_voting_period: { + time: 604800, // in seconds + }, + // time or null + min_voting_period: null, + only_members_execute: true, + pre_propose_info: { + // deposit info or null for none + deposit_info: { + amount: "1000000", + denom: { + // One of token | voting_module_token must be used + token: { + denom: { + // native with denom | cw20 with address + native: "uixo", + }, + }, + // voting_module_token: {} + }, + // 'always' | 'only_passed' | 'never' + refund_policy: "only_passed", + }, + open_proposal_submission: false, + }, + threshold: { + // One of threshold_quorum | absolute_percentage | absolute_count must be used + // threshold_quorum: { + // quorum: { + // percent: "0.30", // "{0.60}" if want percentage, then set majority to undefined + // majority: undefined, // {} if want majority, then set percentage to undefined + // }, + // threshold: { + // percent: undefined, // "{0.40}" if want percentage, then set majority to undefined + // majority: {}, // {} if want majority, then set percentage to undefined + // }, + // }, + // absolute_percentage: { + // percent: "0.50", // "{0.50}" if want percentage, then set majority to undefined + // majority: undefined, // {} if want majority, then set percentage to undefined + // }, + absolute_count: { + threshold: "2", + }, + }, + }, + // voting_module_instantiate_info can be one of the cases or null + // 'membership' | 'multisig' + voting_module_instantiate_info: { + code_id: daoVotingCw4ContractCode, + msg: { + cw4_group_code_id: cw4ContractCode, + initial_members: [ + { addr: "ixo19gxr25tp5x4yky57r9gcpkykjnkph3ee646t2k", weight: 1 }, + ], + }, + }, + // 'staking' with new tokensContract + // voting_module_instantiate_info: { + // code_id: daoVotingCw20StakedContractCode, + // msg: { + // token_info: { + // new: { + // code_id: cw20BaseContractCode, + // decimals: 6, + // marketing: null, + // initial_balances: [ + // { + // address: "ixo19gxr25tp5x4yky57r9gcpkykjnkph3ee646t2k", + // amount: "25", + // }, + // ], + // // token supply (if want 1 million tokens) minus sum of initial balances distributed on top + // initial_dao_balance: "1000000000", // can be null then only initial_balances will be supply + // // token name + // label: "TOKEN", + // // token name + // name: "TOKEN", + // // token symbol, must be 3 chars min + // symbol: "TOK", + // staking_code_id: cw20StakeContractCode, + // unstaking_duration: { + // time: 86400, // in seconds + // }, + // }, + // }, + // active_threshold: null, + // }, + // }, + // 'staking' with old tokensContract + // voting_module_instantiate_info: { + // code_id: daoVotingCw20StakedContractCode, + // msg: { + // token_info: { + // existing: { + // address: "", // tokenContractAddress + // staking_contract: { + // new: { + // staking_code_id: cw20StakeContractCode, + // unstaking_duration: 86400, // in seconds + // }, + // }, + // }, + // }, + // active_threshold: null, + // }, + // }, + }, + members_group: { + name: "Members", + description: "Members group", + image_url: + "https://sienaconstruction.com/wp-content/uploads/2017/05/test-image.jpg", + proposal_modules_instantiate_info: { + allow_revoting: false, + close_proposal_on_execution_failure: true, + max_voting_period: { + time: 604800, // in seconds + }, + // time or null + min_voting_period: null, + only_members_execute: true, + pre_propose_info: { + // deposit info or null for none + deposit_info: { + amount: "1000000", + denom: { + // One of token | voting_module_token must be used + token: { + denom: { + // native with denom | cw20 with address + native: "uixo", + }, + }, + // voting_module_token: {} + }, + // 'always' | 'only_passed' | 'never' + refund_policy: "only_passed", + }, + open_proposal_submission: false, + }, + threshold: { + // One of threshold_quorum | absolute_percentage | absolute_count must be used + threshold_quorum: { + quorum: { + percent: "0.30", // "{0.60}" if want percentage, then set majority to undefined + majority: undefined, // {} if want majority, then set percentage to undefined + }, + threshold: { + percent: undefined, // "{0.40}" if want percentage, then set majority to undefined + majority: {}, // {} if want majority, then set percentage to undefined + }, + }, + // absolute_percentage: { + // percent: "0.50", // "{0.50}" if want percentage, then set majority to undefined + // majority: undefined, // {} if want majority, then set percentage to undefined + // }, + // absolute_count: { + // threshold: "2", + // }, + }, + }, + // voting_module_instantiate_info can be one of the cases or null + // 'membership' | 'multisig' + // voting_module_instantiate_info: { + // code_id: daoVotingCw4ContractCode, + // msg: { + // cw4_group_code_id: cw4ContractCode, + // initial_members: [ + // { addr: "ixo19gxr25tp5x4yky57r9gcpkykjnkph3ee646t2k", weight: 1 }, + // ], + // }, + // }, + // 'staking' with new tokensContract + voting_module_instantiate_info: { + code_id: daoVotingCw20StakedContractCode, + msg: { + token_info: { + new: { + code_id: cw20BaseContractCode, + decimals: 6, + marketing: null, + initial_balances: [ + { + address: "ixo19gxr25tp5x4yky57r9gcpkykjnkph3ee646t2k", + amount: "25", + }, + ], + // token supply (if want 1 million tokens) minus sum of initial balances distributed on top + initial_dao_balance: "1000000000", // can be null then only initial_balances will be supply + // token name + label: "IMPACT", + // token name + name: "IMPACT", + // token symbol, must be 3 chars min + symbol: "IMPACT", + staking_code_id: cw20StakeContractCode, + unstaking_duration: { + time: 86400, // in seconds + }, + }, + }, + active_threshold: null, + }, + }, + // 'staking' with old tokensContract + // voting_module_instantiate_info: { + // code_id: daoVotingCw20StakedContractCode, + // msg: { + // token_info: { + // existing: { + // address: "", // tokenContractAddress + // staking_contract: { + // new: { + // staking_code_id: cw20StakeContractCode, + // unstaking_duration: 86400, // in seconds + // }, + // }, + // }, + // }, + // active_threshold: null, + // }, + // }, + }, +}); + +export const setup_dao_constants = ({ + management, + groupAddresses, +}: { + management: string; + groupAddresses: string[]; // for each group address a linkedEntity will be created +}) => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "dao", + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: undefined, + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: "", + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + verification: [ + { + relationships: ["authentication"], + method: { + id: `{id}#${management}`, + type: "CosmosAccountAddress", + blockchainAccountID: management, + controller: "{id}", + }, + }, + ], + // for each group address a linkedEntity will be created + groupAddresses, + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "The Impact DAO cooperative makes outcomes-based investments into innovations, projects and ventures that can dleiver Internet of Impact solutions. Members of the DAO are pioneering innovators, investors, builders, and implementors who contribute capital, work, open-source software, and market access opportunities. The DAO treasury provides financing for the ecosystem by growing a portfolio of assets and by generating revenues from its investments. The DAO Tokens represent each member's participation share in the treasury that can be exchanged after the DAO breaks even. More recent investors recive a liquidation preference.", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Market Relayer"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "Impact DAO 1", + image: + "https://thumbs.dreamstime.com/b/environment-earth-day-hands-trees-growing-seedlings-bokeh-green-background-female-hand-holding-tree-nature-field-gra-130247647.jpg", + logo: "logoLink", + brand: "Impact DAO", + location: "Global", + description: + "The Impact DAO cooperative consists of participants who are building the Internet of Impact to address sustainable development, human security, energy transitions, and ecological regeneration..", + attributes: [ + { + key: "Model", + value: "MimiMoto", + }, + { + key: "Location", + value: "Global", + }, + { + key: "Usage", + value: "Global", + }, + { + key: "Product", + value: "Impact DAO tokens", + }, + ], + metrics: [ + { + prefix: "$IMPACT", + metric: "Token Price", + suffix: "", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +// Types for typescript strict type checking, please ignore +export type SetupDaoConstantFields = ReturnType; +export type SetupGroupConstantKeys = keyof ReturnType< + typeof setup_group_constants +>; +export type ChainNetwork = "devnet" | "testnet" | "mainnet"; +export type LinkedResourcesUploaded = { + name: string; + cid: string; + type: string; + storage: "cellnode" | "ipfs"; +}[]; diff --git a/__tests__/setup/fullExample/setupFlow.ts b/__tests__/setup/fullExample/setupFlow.ts new file mode 100644 index 00000000..00cef450 --- /dev/null +++ b/__tests__/setup/fullExample/setupFlow.ts @@ -0,0 +1,174 @@ +import { + customQueries, + generateNewWallet, + sendFromFaucet, + testMsg, + utils, +} from "../../helpers/common"; +import { WalletUsers } from "../../helpers/constants"; +import * as Iid from "../Iid"; +import * as IidMain from "../../modules/Iid"; +import * as Wasm from "../../modules/CosmWasm"; +import { createGroupMsg } from "../Groups"; +import { + chainNetwork, + LinkedResourcesUploaded, + SetupGroupConstantKeys, + setup_dao_constants, +} from "./constants"; +import * as Entity from "../Entity"; + +export const impactsFlow = () => + describe("Flow for creating a Entity (dao/protocol/oracle)", () => { + // =============================================================== + // Set Testers mnemonic to env variable and ledger root user did + // =============================================================== + + // below test can fail as user might already be ledgered, that is ok + beforeAll(() => + generateNewWallet(WalletUsers.tester, process.env.TESTER_MNEMONIC) + ); + + // @ts-ignore + if (chainNetwork != "mainnet") { + // Send from faucet for devnet/testnet + sendFromFaucet(WalletUsers.tester); + } + testMsg("/ixo.iid.v1beta1.MsgCreateIidDocument", () => + IidMain.CreateIidDoc(WalletUsers.tester) + ); + + // =============================================================== + // Create dao dao groups + // =============================================================== + let groupFromConstants: SetupGroupConstantKeys; + + // below is a generic function, you can copy it to make more groups, you only need to: + // 1 - ensure to have created a correlating constant group in setup_group_constants() function + // in the constants.ts file + // 2 - define the variable as below to save the group address and change it in function + // 3 - change the groupFromConstants to the one you want to use + // =============================== START + let management_group: string; + testMsg("/cosmwasm.wasm.v1.MsgInstantiateContract dao core", async () => { + groupFromConstants = "management_group"; + const res = await Wasm.WasmInstantiateTrx( + customQueries.contract.getContractCode(chainNetwork, "dao_core")!, + JSON.stringify(createGroupMsg(chainNetwork, groupFromConstants)) + ); + management_group = utils.common.getValueFromEvents( + res, + "instantiate", + "_contract_address" + ); + if (res.code != 0 || !management_group) { + console.log(res); + throw new Error(res.rawLog); + } + console.log({ management_group }); + const didRes = await Iid.CreateIidDocForGroup(management_group); + return didRes; + }); + // =============================== END + + // =============================== START + let members_group: string; + testMsg("/cosmwasm.wasm.v1.MsgInstantiateContract dao core", async () => { + groupFromConstants = "members_group"; + const res = await Wasm.WasmInstantiateTrx( + customQueries.contract.getContractCode(chainNetwork, "dao_core")!, + JSON.stringify(createGroupMsg(chainNetwork, groupFromConstants)) + ); + members_group = utils.common.getValueFromEvents( + res, + "instantiate", + "_contract_address" + ); + if (res.code != 0 || !members_group) { + console.log(res); + throw new Error(res.rawLog); + } + console.log({ members_group }); + const didRes = await Iid.CreateIidDocForGroup(members_group); + return didRes; + }); + // =============================== END + + // =============================================================== + // Create Entities + // =============================================================== + // You can create all your entities below, you can just copy a whole entity creation and make + // as many as you want, just ensure you have all the groups needed that will be used and that for each + // entity there is a corresponding exported setup_{name}_constants that you can use for the entity + + // you can customize a few things below as follows: + // 1 - choose which group is the management group, which will be added to the entities verification methods + // 2 - add more groups to groupAddresses and they will be added as linkedEntities + // =============================== START + let daoDid: string; + let adminAccount: string; + let linkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_dao_constants({ + management: management_group, + groupAddresses: [management_group, members_group], + }); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ linkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + linkedResourcesUploaded + ); + daoDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + adminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ daoDid, adminAccount }); + + // Transfer Entity to group + // choose inside generateCosmwasmDid() function which group + // is the owner group, to which the dao will be transfered to + const resTransfer = await Entity.TransferEntity( + daoDid, + utils.did.generateCosmwasmDid(members_group) + ); + return resTransfer; + }); + // =============================== END + }); diff --git a/__tests__/setup/impacts/constants.ts b/__tests__/setup/impacts/constants.ts new file mode 100644 index 00000000..dcc669cf --- /dev/null +++ b/__tests__/setup/impacts/constants.ts @@ -0,0 +1,148 @@ +import { cellNodeChainMapping } from "../../../src/custom_queries/cellnode"; +import { dids } from "../constants"; +import { chainNetwork } from "../index.setup.spec"; + +export const setup_dao_constants = () => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "dao", + // TODO DAO itself, determine deterministically + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: "", + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: dids.daoClass, + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + // TODO need own impacts cellnode + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "The Impact DAO cooperative makes outcomes-based investments into innovations, projects and ventures that can deliver Internet of Impact solutions. Members of the DAO are pioneering innovators, investors, builders, and implementors who contribute capital, work, open-source software, and market access opportunities. The DAO treasury provides financing for the ecosystem by growing a portfolio of assets and by generating revenues from its investments. The DAO Tokens represent each member's participation share in the treasury that can be exchanged after the DAO breaks even. More recent investors receive a liquidation preference.", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Cooperative"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "Impact DAO 1", + image: + "https://thumbs.dreamstime.com/b/environment-earth-day-hands-trees-growing-seedlings-bokeh-green-background-female-hand-holding-tree-nature-field-gra-130247647.jpg", + logo: "logoLink", + brand: "Impact DAO", + location: "Global", + description: + "The Impact DAO cooperative consists of participants who are building the Internet of Impact to address sustainable development, human security, energy transitions, and ecological regeneration..", + attributes: [ + { + key: "Model", + value: "MimiMoto", + }, + { + key: "Location", + value: "Global", + }, + { + key: "Usage", + value: "Global", + }, + { + key: "Product", + value: "Impact DAO tokens", + }, + ], + metrics: [ + { + prefix: "$IMPACT", + metric: "Token Price", + suffix: "", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +// Types for typescript strict type checking, please ignore +export type SetupDaoConstantFields = ReturnType; diff --git a/__tests__/setup/impacts/setupFlow.ts b/__tests__/setup/impacts/setupFlow.ts new file mode 100644 index 00000000..74f2248b --- /dev/null +++ b/__tests__/setup/impacts/setupFlow.ts @@ -0,0 +1,99 @@ +import { + customQueries, + generateNewWallet, + sendFromFaucet, + testMsg, + utils, +} from "../../helpers/common"; +import { WalletUsers } from "../../helpers/constants"; +import * as IidMain from "../../modules/Iid"; +import { setup_dao_constants } from "./constants"; +import * as Entity from "../Entity"; +import { chainNetwork } from "../index.setup.spec"; +import { LinkedResourcesUploaded } from "../constants"; + +export const impactsFlow = () => + describe("Flow for creating a Entity (dao/protocol/oracle)", () => { + // =============================================================== + // Set Testers mnemonic to env variable and ledger root user did + // =============================================================== + + // below test can fail as user might already be ledgered, that is ok + beforeAll(() => + generateNewWallet(WalletUsers.tester, process.env.TESTER_MNEMONIC) + ); + + // @ts-ignore + if (chainNetwork != "mainnet") { + // Send from faucet for devnet/testnet + sendFromFaucet(WalletUsers.tester); + } + testMsg("/ixo.iid.v1beta1.MsgCreateIidDocument", () => + IidMain.CreateIidDoc(WalletUsers.tester) + ); + + // =============================================================== + // Create Entities + // =============================================================== + // You can create all your entities below, you can just copy a whole entity creation and make + // as many as you want, just ensure you have all the groups needed that will be used and that for each + // entity there is a corresponding exported setup_{name}_constants that you can use for the entity + + // =============================== START + let daoDid: string; + let adminAccount: string; + let linkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_dao_constants(); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ linkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + linkedResourcesUploaded + ); + daoDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + adminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ daoDid, adminAccount }); + + return res; + }); + // =============================== END + }); diff --git a/__tests__/setup/index.setup.spec.ts b/__tests__/setup/index.setup.spec.ts new file mode 100644 index 00000000..44c08ed9 --- /dev/null +++ b/__tests__/setup/index.setup.spec.ts @@ -0,0 +1,38 @@ +require("dotenv").config(); + +import { ChainNetwork } from "../../src/custom_queries/chain.types"; +import { generateWallets } from "../helpers/common"; +import { classesFlow } from "./classes/setupFlow"; +import { ecsFlow } from "./ecs/setupFlow"; +import { emergingDaoFlow, emergingProtocolsFlow } from "./emerging/setupFlow"; +import { impactsFlow } from "./impacts/setupFlow"; +import { propectFlow } from "./prospect/setupFlow"; +import { scalnyxFlow } from "./scalnyx/setupFlow"; +import { supamotoFlow } from "./supamoto/setupFlow"; + +export const chainNetwork: ChainNetwork = "devnet"; + +beforeAll(() => generateWallets(false)); + +// Setup flow for dao and group creations +// ------------------------------------------ + +// first create god classes and save dids in ./constants.ts +classesFlow(); + +// next create impacts dao and save did in ./constants.ts +impactsFlow(); + +// next create emerging dao to save did to ./constants.ts +emergingDaoFlow(); + +// next create emerging protocols and save cookstoveAssetProtocol to ./constants.ts +emergingProtocolsFlow(); + +// next create daos and oracles and save oracles dids to ./constants.ts +propectFlow(); +scalnyxFlow(); + +// next can create the other daos etc +ecsFlow(); +supamotoFlow(); diff --git a/__tests__/setup/prospect/constants.ts b/__tests__/setup/prospect/constants.ts new file mode 100644 index 00000000..3372d2cf --- /dev/null +++ b/__tests__/setup/prospect/constants.ts @@ -0,0 +1,286 @@ +import { cellNodeChainMapping } from "../../../src/custom_queries/cellnode"; +import { dids } from "../constants"; +import { chainNetwork } from "../index.setup.spec"; + +export const setup_dao_constants = () => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "dao", + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: dids.impactsDao, + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: dids.daoClass, + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "The Impact DAO cooperative makes outcomes-based investments into innovations, projects and ventures that can dleiver Internet of Impact solutions. Members of the DAO are pioneering innovators, investors, builders, and implementors who contribute capital, work, open-source software, and market access opportunities. The DAO treasury provides financing for the ecosystem by growing a portfolio of assets and by generating revenues from its investments. The DAO Tokens represent each member's participation share in the treasury that can be exchanged after the DAO breaks even. More recent investors recive a liquidation preference.", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Market Relayer"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "Impact DAO 1", + image: + "https://thumbs.dreamstime.com/b/environment-earth-day-hands-trees-growing-seedlings-bokeh-green-background-female-hand-holding-tree-nature-field-gra-130247647.jpg", + logo: "logoLink", + brand: "Impact DAO", + location: "Global", + description: + "The Impact DAO cooperative consists of participants who are building the Internet of Impact to address sustainable development, human security, energy transitions, and ecological regeneration..", + attributes: [ + { + key: "Model", + value: "MimiMoto", + }, + { + key: "Location", + value: "Global", + }, + { + key: "Usage", + value: "Global", + }, + { + key: "Product", + value: "Impact DAO tokens", + }, + ], + metrics: [ + { + prefix: "$IMPACT", + metric: "Token Price", + suffix: "", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +export const setup_oracle_constants = () => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "oracle/evaluation", + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: dids.emergingDao, + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: dids.oracleClass, + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "The Impact DAO cooperative makes outcomes-based investments into innovations, projects and ventures that can dleiver Internet of Impact solutions. Members of the DAO are pioneering innovators, investors, builders, and implementors who contribute capital, work, open-source software, and market access opportunities. The DAO treasury provides financing for the ecosystem by growing a portfolio of assets and by generating revenues from its investments. The DAO Tokens represent each member's participation share in the treasury that can be exchanged after the DAO breaks even. More recent investors recive a liquidation preference.", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Market Relayer"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "Impact DAO 1", + image: + "https://thumbs.dreamstime.com/b/environment-earth-day-hands-trees-growing-seedlings-bokeh-green-background-female-hand-holding-tree-nature-field-gra-130247647.jpg", + logo: "logoLink", + brand: "Impact DAO", + location: "Global", + description: + "The Impact DAO cooperative consists of participants who are building the Internet of Impact to address sustainable development, human security, energy transitions, and ecological regeneration..", + attributes: [ + { + key: "Model", + value: "MimiMoto", + }, + { + key: "Location", + value: "Global", + }, + { + key: "Usage", + value: "Global", + }, + { + key: "Product", + value: "Impact DAO tokens", + }, + ], + metrics: [ + { + prefix: "$IMPACT", + metric: "Token Price", + suffix: "", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +// Types for typescript strict type checking, please ignore +export type SetupDaoConstantFields = ReturnType; diff --git a/__tests__/setup/prospect/setupFlow.ts b/__tests__/setup/prospect/setupFlow.ts new file mode 100644 index 00000000..7425ecd9 --- /dev/null +++ b/__tests__/setup/prospect/setupFlow.ts @@ -0,0 +1,157 @@ +import { + customQueries, + generateNewWallet, + sendFromFaucet, + testMsg, + utils, +} from "../../helpers/common"; +import { WalletUsers } from "../../helpers/constants"; +import * as IidMain from "../../modules/Iid"; +import { setup_dao_constants, setup_oracle_constants } from "./constants"; +import * as Entity from "../Entity"; +import { chainNetwork } from "../index.setup.spec"; +import { LinkedResourcesUploaded } from "../constants"; + +export const propectFlow = () => + describe("Flow for creating a Entity (dao/protocol/oracle)", () => { + // =============================================================== + // Set Testers mnemonic to env variable and ledger root user did + // =============================================================== + + // below test can fail as user might already be ledgered, that is ok + beforeAll(() => + generateNewWallet(WalletUsers.tester, process.env.TESTER_MNEMONIC) + ); + + // @ts-ignore + if (chainNetwork != "mainnet") { + // Send from faucet for devnet/testnet + sendFromFaucet(WalletUsers.tester); + } + testMsg("/ixo.iid.v1beta1.MsgCreateIidDocument", () => + IidMain.CreateIidDoc(WalletUsers.tester) + ); + + // =============================================================== + // Create Entities + // =============================================================== + // You can create all your entities below, you can just copy a whole entity creation and make + // as many as you want, just ensure you have all the groups needed that will be used and that for each + // entity there is a corresponding exported setup_{name}_constants that you can use for the entity + + // =============================== START + let daoDid: string; + let adminAccount: string; + let linkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_dao_constants(); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ linkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + linkedResourcesUploaded + ); + daoDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + adminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ daoDid, adminAccount }); + + return res; + }); + // =============================== END + + // =============================== START + let oracleDid: string; + let oracleAdminAccount: string; + let oracleLinkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_oracle_constants(); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + oracleLinkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + oracleLinkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ oracleLinkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + oracleLinkedResourcesUploaded + ); + oracleDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + oracleAdminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ oracleDid, oracleAdminAccount }); + + return res; + }); + // =============================== END + }); diff --git a/__tests__/setup/scalnyx/constants.ts b/__tests__/setup/scalnyx/constants.ts new file mode 100644 index 00000000..65e11bf5 --- /dev/null +++ b/__tests__/setup/scalnyx/constants.ts @@ -0,0 +1,287 @@ +import { cellNodeChainMapping } from "../../../src/custom_queries/cellnode"; +import { dids } from "../constants"; +import { chainNetwork } from "../index.setup.spec"; + +export const setup_dao_constants = () => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "dao", + // TODO create classes first as need impacts dao + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: dids.impactsDao, + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: dids.daoClass, + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "The Impact DAO cooperative makes outcomes-based investments into innovations, projects and ventures that can dleiver Internet of Impact solutions. Members of the DAO are pioneering innovators, investors, builders, and implementors who contribute capital, work, open-source software, and market access opportunities. The DAO treasury provides financing for the ecosystem by growing a portfolio of assets and by generating revenues from its investments. The DAO Tokens represent each member's participation share in the treasury that can be exchanged after the DAO breaks even. More recent investors recive a liquidation preference.", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Market Relayer"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "Impact DAO 1", + image: + "https://thumbs.dreamstime.com/b/environment-earth-day-hands-trees-growing-seedlings-bokeh-green-background-female-hand-holding-tree-nature-field-gra-130247647.jpg", + logo: "logoLink", + brand: "Impact DAO", + location: "Global", + description: + "The Impact DAO cooperative consists of participants who are building the Internet of Impact to address sustainable development, human security, energy transitions, and ecological regeneration..", + attributes: [ + { + key: "Model", + value: "MimiMoto", + }, + { + key: "Location", + value: "Global", + }, + { + key: "Usage", + value: "Global", + }, + { + key: "Product", + value: "Impact DAO tokens", + }, + ], + metrics: [ + { + prefix: "$IMPACT", + metric: "Token Price", + suffix: "", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +export const setup_oracle_constants = () => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "oracle/evaluation", + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: dids.emergingDao, + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: dids.oracleClass, + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "The Impact DAO cooperative makes outcomes-based investments into innovations, projects and ventures that can dleiver Internet of Impact solutions. Members of the DAO are pioneering innovators, investors, builders, and implementors who contribute capital, work, open-source software, and market access opportunities. The DAO treasury provides financing for the ecosystem by growing a portfolio of assets and by generating revenues from its investments. The DAO Tokens represent each member's participation share in the treasury that can be exchanged after the DAO breaks even. More recent investors recive a liquidation preference.", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Market Relayer"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "Impact DAO 1", + image: + "https://thumbs.dreamstime.com/b/environment-earth-day-hands-trees-growing-seedlings-bokeh-green-background-female-hand-holding-tree-nature-field-gra-130247647.jpg", + logo: "logoLink", + brand: "Impact DAO", + location: "Global", + description: + "The Impact DAO cooperative consists of participants who are building the Internet of Impact to address sustainable development, human security, energy transitions, and ecological regeneration..", + attributes: [ + { + key: "Model", + value: "MimiMoto", + }, + { + key: "Location", + value: "Global", + }, + { + key: "Usage", + value: "Global", + }, + { + key: "Product", + value: "Impact DAO tokens", + }, + ], + metrics: [ + { + prefix: "$IMPACT", + metric: "Token Price", + suffix: "", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +// Types for typescript strict type checking, please ignore +export type SetupDaoConstantFields = ReturnType; diff --git a/__tests__/setup/scalnyx/setupFlow.ts b/__tests__/setup/scalnyx/setupFlow.ts new file mode 100644 index 00000000..7ff9317c --- /dev/null +++ b/__tests__/setup/scalnyx/setupFlow.ts @@ -0,0 +1,162 @@ +import { + customQueries, + generateNewWallet, + sendFromFaucet, + testMsg, + utils, +} from "../../helpers/common"; +import { WalletUsers } from "../../helpers/constants"; +import * as IidMain from "../../modules/Iid"; +import { setup_dao_constants, setup_oracle_constants } from "./constants"; +import * as Entity from "../Entity"; +import { chainNetwork } from "../index.setup.spec"; +import { LinkedResourcesUploaded } from "../constants"; + +export const scalnyxFlow = () => + describe("Flow for creating a Entity (dao/protocol/oracle)", () => { + // =============================================================== + // Set Testers mnemonic to env variable and ledger root user did + // =============================================================== + + // below test can fail as user might already be ledgered, that is ok + beforeAll(() => + beforeAll(() => + Promise.all([ + generateNewWallet(WalletUsers.tester, process.env.TESTER_MNEMONIC), + generateNewWallet(WalletUsers.alice, process.env.ED_KEYS_MNEMONIC), + ]) + ) + ); + + // @ts-ignore + if (chainNetwork != "mainnet") { + // Send from faucet for devnet/testnet + sendFromFaucet(WalletUsers.tester); + } + testMsg("/ixo.iid.v1beta1.MsgCreateIidDocument", () => + IidMain.CreateIidDoc(WalletUsers.tester) + ); + + // =============================================================== + // Create Entities + // =============================================================== + // You can create all your entities below, you can just copy a whole entity creation and make + // as many as you want, just ensure you have all the groups needed that will be used and that for each + // entity there is a corresponding exported setup_{name}_constants that you can use for the entity + + // =============================== START + let daoDid: string; + let adminAccount: string; + let linkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_dao_constants(); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ linkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + linkedResourcesUploaded + ); + daoDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + adminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ daoDid, adminAccount }); + + return res; + }); + // =============================== END + + // =============================== START + let oracleDid: string; + let oracleAdminAccount: string; + let oracleLinkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_oracle_constants(); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + oracleLinkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + oracleLinkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ oracleLinkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + oracleLinkedResourcesUploaded + ); + oracleDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + oracleAdminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ oracleDid, oracleAdminAccount }); + + return res; + }); + // =============================== END + }); diff --git a/__tests__/setup/supamoto/constants.ts b/__tests__/setup/supamoto/constants.ts new file mode 100644 index 00000000..5150a9b7 --- /dev/null +++ b/__tests__/setup/supamoto/constants.ts @@ -0,0 +1,190 @@ +import { cellNodeChainMapping } from "../../../src/custom_queries/cellnode"; +import { dids } from "../constants"; +import { chainNetwork } from "../index.setup.spec"; + +export const setup_dao_constants = () => ({ + entity: { + // type of entity eg dao/protocol/asset/oracle + entityType: "dao", + // please use Impact DAO's did as relayerNode eg dids.impactsDao + relayerNode: dids.impactsDao, + // for context class below please use the parent dao/protocol/asset class did provided by ixo eg dids.daoClass + contextClass: dids.daoClass, + // can add a also know ass if want + alsoKnownAs: "", + // you can remove/add more services + service: [ + { + id: "{id}#cellnode", + type: "Cellnode", + serviceEndpoint: cellNodeChainMapping[chainNetwork], + }, + { + id: "{id}#ipfs", + type: "Ipfs", + serviceEndpoint: "https://ipfs.io/ipfs/", + }, + ], + // if you have any other linked resources other than the ones below that will automatically + // be uploaded to cellnode/w3s, you can pass them here + linkedResources: [ + // { + // id: `{id}#id`, + // type: "type", + // description: "name", + // mediaType: "application/ld+json", + // serviceEndpoint: `cellnode:/public/${cid}`, + // proof: cid, + // encrypted: "false", + // right: "", + // }, + ], + }, + // you can create linked resources that will be uploaded to the specified storage and resource will be saved + // on entity linked resources with the cid as proof and service endpoint of provided storage. + linkedResources: [ + { + name: "page", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#page", + page: { + id: "IrCcJ8hl8t", + type: "paragraph", + data: { + text: "A SupaMoto NFT owner has the right to continuously claim the carbon emission reductions produced by a household using a SupaMoto smart cookstove. The household receives a cookstove device at no cost and only pays for renewable biomass pellets. This saves households up to 50% on their monthly cooking energy expenditure, compared to purchasing polluting fuels such as charcoal. When carbon emission reductions are verified CARBON credit tokens get generated to your account. The CARBON balance in your account can be used to offset your own footprint, shared with others, or swapped for digital cash. Climate Impacts and Socio-economic benefits: Clean cooking provides environmental, economic and societal benefits. It reduces greenhouse gas emissions and mitigates environmental degradation. Emerging economy households save on fuel costs and this improves their financial stability. Clean cooking can improve health by reducing indoor air pollution and the risks of fires, particularly for women and children who are most exposed to toxic smoke inhalation. Clean cooking has the potential to empower women and promote gender equality by improving their health, reducing their workload, and increasing their financial independence and decision-making power. Scaling access to clean cooking in communities stimulates the local economy by creating new job opportunities in the promotion, distribution, and maintenance of clean cookstoves. How it works:", + }, + }, + }, + }, + { + name: "tags", + type: "Settings", + storage: "cellnode", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + type: "ixo:entity#tags", + ddoTags: [ + { + category: "dao", + tags: ["Market Relayer"], + }, + ], + }, + }, + { + name: "profile", + type: "Settings", + storage: "ipfs", + json: { + "@context": { + ixo: "https://w3id.org/ixo/ns/protocol/", + "@id": "@type", + type: "@type", + "@protected": true, + }, + id: "ixo:entity#profile", + type: "profile", + name: "SupaMoto Malawi", + image: "imageLink", + logo: "logoLink", + brand: "SupaMoto", + location: "MW", + description: + "The SupaMoto clean cookstove is a smart, IoT-connected device that helps households cut carbon emissions while cooking with affordable and renewable biomass fuel. This convenient solution offers a more cost-effective, healthy, and time-saving alternative to traditional cooking methods.", + attributes: [ + { + key: "Model", + value: "MimiMoto", + }, + { + key: "Location", + value: "Malawi", + }, + { + key: "Fuel", + value: "Renewable Biomass Pellets", + }, + { + key: "Usage", + value: "Domestic", + }, + { + key: "Conversion", + value: "1kg = 0.01 credits", + }, + { + key: "Product", + value: "CARBON credit tokens", + }, + ], + metrics: [ + { + prefix: "USD", + metric: "Token Price", + suffix: "Average/NFT", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Credits", + metric: "CARBON", + suffix: "/month (moving average)", + source: "https://example.com/dfdfcv", + }, + { + prefix: "Performance", + metric: "Alpha", + suffix: "", + source: "https://example.com/dfdfcv", + }, + ], + }, + }, + ], +}); + +// Types for typescript strict type checking, please ignore +export type SetupDaoConstantFields = ReturnType; + +export const cookstoveIds = [ + 202200001, 202200005, 202200007, 202200009, 202200010, 202200011, 202200012, + 202200013, 202200015, 202200016, 202200018, 202200020, 202200025, 202200028, + 202200034, 202200096, 202200099, 202200111, 202200189, 202200301, 202200309, + 202200372, 202200388, 310000004, 310000076, 310000095, 310000115, 310000163, + 310000205, 310000267, 310000341, 310000343, 310000405, 310000624, 310000745, + 310000749, 310000771, 310000774, 310000832, 310000879, 310001162, 310001224, + 310001353, 310001365, 310001421, 310001742, 310001813, 310001819, 310001856, + 310001864, 310001999, 310002006, 310002066, 310002108, 310002165, 310002195, + 310002214, 310002352, 310002365, 310002511, 310002578, 310002653, 310002766, + 310002768, 310002884, 310003024, 310003076, 310003080, 310003551, 310003633, + 310005726, 310007811, 310008327, 310008752, 310008928, 310008934, 310008961, + 310009369, 310009945, 310012706, 310013456, 310013483, 310014068, 310014791, + 310014870, 310014932, 310015802, 310015897, 310015928, 310016233, 310017019, + 310017126, 310017236, 310017478, 310017571, 310017700, 310018042, 310018331, + 310019032, 310019080, 310020612, 310020614, 310020762, 310020954, 310021047, + 310021108, 310021222, 310021223, 310021225, 310021338, 310021351, 310021358, + 310021407, 310021489, 310021816, 310021823, 310021918, 310021992, 310022093, + 310022125, 310022157, 310022158, 310022211, 310022219, 310022225, 310022273, + 310022288, 310022314, 310022421, 310022515, 310022697, 310022719, 310022784, + 310022811, 310022840, 310022888, 310022931, 310023055, 310023068, 310023074, + 310023118, 310023153, 310023212, 310023245, 310023283, 310023547, 310025085, + 310025198, 310025200, 310025233, 310025300, 310025325, 310025390, 310025398, + 310025409, 310025446, 310025570, 310028308, 310028764, 310029142, 310029182, + 310029369, 310029441, 310029811, 310029997, 310030266, 310030442, 310030721, + 310031447, 310032389, 310032587, 310032589, 310032590, 310032701, 310032952, + 310032962, 310032963, 310032969, 310032989, 310033438, 310033439, 310034102, + 310034281, 310035031, 310035220, 310035244, 310035247, 310035265, 310035385, + 310035508, 310036019, 310036122, 310036958, 310037403, 310038361, +]; diff --git a/__tests__/setup/supamoto/setupFlow.ts b/__tests__/setup/supamoto/setupFlow.ts new file mode 100644 index 00000000..a60ff448 --- /dev/null +++ b/__tests__/setup/supamoto/setupFlow.ts @@ -0,0 +1,409 @@ +import { + customQueries, + generateNewWallet, + getFileFromPath, + sendFromFaucet, + testMsg, + utils, +} from "../../helpers/common"; +import { WalletUsers } from "../../helpers/constants"; +import * as IidMain from "../../modules/Iid"; +import { cookstoveIds, setup_dao_constants } from "./constants"; +import * as Entity from "../Entity"; +import * as Entity1 from "../../modules/Entity"; +import { chainNetwork } from "../index.setup.spec"; +import { LinkedResourcesUploaded, dids } from "../constants"; + +export const supamotoFlow = () => + describe("Flow for creating a Entity (dao/protocol/oracle)", () => { + // =============================================================== + // Set Testers mnemonic to env variable and ledger root user did + // =============================================================== + + // below test can fail as user might already be ledgered, that is ok + beforeAll(() => + generateNewWallet(WalletUsers.tester, process.env.TESTER_MNEMONIC) + ); + + // @ts-ignore + if (chainNetwork != "mainnet") { + // Send from faucet for devnet/testnet + sendFromFaucet(WalletUsers.tester); + } + testMsg("/ixo.iid.v1beta1.MsgCreateIidDocument", () => + IidMain.CreateIidDoc(WalletUsers.tester) + ); + + // =============================================================== + // Create Entities + // =============================================================== + // You can create all your entities below, you can just copy a whole entity creation and make + // as many as you want, just ensure you have all the groups needed that will be used and that for each + // entity there is a corresponding exported setup_{name}_constants that you can use for the entity + + // =============================== START + let daoDid: string; + let adminAccount: string; + let linkedResourcesUploaded: LinkedResourcesUploaded = []; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity dao", async () => { + const daoConst = setup_dao_constants(); + + // Uploading linkedResources + for (const { name, type, storage, json } of daoConst.linkedResources) { + if (storage === "cellnode") { + const cellnode = await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: cellnode.key, + type, + storage, + }); + } else if (storage === "ipfs") { + const web3 = await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + Buffer.from(JSON.stringify(json)).toString("base64"), + undefined, + chainNetwork + ); + linkedResourcesUploaded.push({ + name, + cid: web3.cid, + type, + storage, + }); + } + } + console.log({ linkedResourcesUploaded }); + + // Create the Entity + const res = await Entity.CreateEntity( + daoConst.entity, + linkedResourcesUploaded + ); + daoDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + adminAccount = utils.common.getValueFromEvents( + res, + "ixo.entity.v1beta1.EntityCreatedEvent", + "entity", + (s) => s.accounts.find((a) => a.name === "admin").address + ); + console.log({ daoDid, adminAccount }); + + return res; + }); + // =============================== END + }); + +export const cookstovesFlow = () => + describe("Testing the Supamoto nfts flow", () => { + // =============================================================== + // Set Testers mnemonic to env variable and ledger root user did + // =============================================================== + + // below test can fail as user might already be ledgered, that is ok + beforeAll(() => + Promise.all([ + generateNewWallet(WalletUsers.tester, process.env.TESTER_MNEMONIC), + generateNewWallet(WalletUsers.alice, process.env.ED_KEYS_MNEMONIC), + ]) + ); + + // @ts-ignore + if (chainNetwork != "mainnet") { + // Send from faucet for devnet/testnet + sendFromFaucet(WalletUsers.tester); + } + testMsg("/ixo.iid.v1beta1.MsgCreateIidDocument", () => + IidMain.CreateIidDoc(WalletUsers.tester) + ); + + // =============================================================== + // Create all assets + // =============================================================== + + // Create top-level class dao + let daoDid = "did:ixo:entity:eaff254f2fc62aefca0d831bc7361c14"; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity asset", async () => { + const res = await Entity1.CreateEntity("dao"); + daoDid = utils.common.getValueFromEvents(res, "wasm", "token_id"); + console.log({ daoDid }); + return res; + }); + + // Create dao entity which is credential issuer + let daoCredsIssuerDid = "did:ixo:entity:4d94f9b6078432648a755203eed50644"; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity asset", async () => { + const res = await Entity1.CreateEntity("dao", [ + { key: "class", val: daoDid }, + ]); + daoCredsIssuerDid = utils.common.getValueFromEvents( + res, + "wasm", + "token_id" + ); + console.log({ daoCredsIssuerDid }); + return res; + }); + + // Save related images WEB3 + let supaLogo = + "https://bafkreifkl6w55nasgqid22d2cqyxccjktbciefzmiqvcudlq3eoer2mzhi.ipfs.w3s.link"; + let supaNftImage = + "https://bafkreideszg4fdha4tf7ldpecltxbyxbnapb663tkuksk2vcczkzkxppaa.ipfs.w3s.link"; + let ecsLogo = + "https://bafkreigkajsskkswn5jwcmfxhn3rqc7gevzgroacq7ygfz6mzkgo72ej4i.ipfs.w3s.link"; + test("Saving device creds", async () => { + supaLogo = ( + await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "image/png", + getFileFromPath(["documents", "supamoto_logo.png"]), + undefined, + chainNetwork + ) + ).url; + console.log({ supaLogo }); + supaNftImage = ( + await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "image/png", + getFileFromPath(["documents", "supamoto-nft-image.png"]), + undefined, + chainNetwork + ) + ).url; + console.log({ supaNftImage }); + ecsLogo = ( + await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "image/png", + getFileFromPath(["documents", "ecs_logo_flame only.png"]), + undefined, + chainNetwork + ) + ).url; + console.log({ ecsLogo }); + expect(ecsLogo).toBeTruthy(); + }); + + // Save supamoto credsPdf WEB3 + let projectCertDoc = + "bafkreiefafy2u5df4l52yb7vvz32hxrxhcceyaq3z7xww2qlz2fp3ppeum"; + test("Saving projectCertDoc", async () => { + projectCertDoc = ( + await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/pdf", + getFileFromPath([ + "documents", + "MimiMoto report Aprovecho Research Center March 2017.pdf", + ]), + undefined, + chainNetwork + ) + ).cid; + console.log({ projectCertDoc }); + expect(projectCertDoc).toBeTruthy(); + }); + + // Save supamoto profile WEB3 + let profile = "4kavdefz12wlefltwxr"; + test("Saving profile", async () => { + const file = JSON.parse( + getFileFromPath(["documents", "test-supamoto-profile.jsonld"], "ascii") + ); + file["image"] = supaNftImage; + file["logo"] = supaLogo; + let buff = Buffer.from(JSON.stringify(file)); + profile = ( + await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + buff.toString("base64"), + undefined, + chainNetwork + ) + ).key; + console.log({ profile }); + expect(profile).toBeTruthy(); + }); + + // Save supamoto projectCreds WEB3 + let projectCreds = + "bafkreih2oq64xhbgp7vyarcrgw6dcofms4zdmjqms6vnfx32vzwglj6nd4"; + test("Saving projectCert", async () => { + const file = JSON.parse( + getFileFromPath( + ["documents", "test-supamoto-projectCredential.jsonld"], + "ascii" + ) + ); + file["issuer"] = daoCredsIssuerDid; + file["credentialSubject"]["project"]["linkedResources"] = file[ + "credentialSubject" + ]["project"]["linkedResources"].map((lr: any) => ({ + ...lr, + id: `https://ipfs.io/ipfs/${projectCertDoc}`, + proof: projectCertDoc, + })); + let buff = Buffer.from(JSON.stringify(file)); + projectCreds = ( + await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + buff.toString("base64"), + undefined, + chainNetwork + ) + ).cid; + console.log({ projectCreds }); + expect(projectCreds).toBeTruthy(); + }); + + // Save supamoto tags CELLNODE + let tags = "klfh2wqlw9mleflu0u6"; + test("Saving tags", async () => { + tags = ( + await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + getFileFromPath(["documents", "test-supamoto-tags.jsonld"]), + undefined, + chainNetwork + ) + ).key; + console.log({ tags }); + expect(tags).toBeTruthy(); + }); + + // Save supamoto tokenMetadata WEB3 emerging account + let tokenMetadata = + "bafkreie7kbpppoizx7anxxufblfkdfmuy27mppuz2hq4a4uouudweb2sm4"; + test("Saving tokenMetadata", async () => { + const file = JSON.parse( + getFileFromPath( + ["documents", "test-supamoto-token-metadata.json"], + "ascii" + ) + ); + file["image"] = supaLogo; + file["properties"]["icon"] = supaLogo; + let buff = Buffer.from(JSON.stringify(file)); + tokenMetadata = ( + await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + buff.toString("base64"), + undefined, + chainNetwork + ) + ).cid; + console.log({ tokenMetadata }); + expect(tokenMetadata).toBeTruthy(); + }); + + // TODO need protocol to add as template id + // Save supamoto claims CELLNODE + let claims = "gf9m2u5ds6tleflu4a8"; + test("Saving claims", async () => { + claims = ( + await customQueries.cellnode.uploadPublicDoc( + "application/ld+json", + getFileFromPath(["documents", "test-supamoto-claims.jsonld"]), + undefined, + chainNetwork + ) + ).key; + console.log({ claims }); + expect(claims).toBeTruthy(); + }); + + // supamoto-asset-collection + let assetCollectionDid: string; + testMsg("/ixo.entity.v1beta1.MsgCreateEntity asset class", async () => { + const res = await Entity1.CreateEntityAssetSupamoto({ + inheritEntityDid: dids.cookstoveAssetProtocol, + profile, + // page, + // creator, + // administrator, + tags, + claims, + tokenMetadata, + projectCert: projectCreds, + oracles: [dids.prospectOracle, dids.scalnyxOracle], + relayerDid: dids.emergingDao, + }); + assetCollectionDid = utils.common.getValueFromEvents( + res, + "wasm", + "token_id" + ); + console.log({ assetCollectionDid }); + return res; + }); + + // Create a batch of Asset entities for the individual Supamoto assets + let assetInstanceDids: string[] = []; + + cookstoveIds.map((id, i) => + testMsg( + `/ixo.entity.v1beta1.MsgCreateEntity asset instance index:${ + i + 1 + } for id:${id}`, + async () => { + let deviceCreds: string; + const file = JSON.parse( + getFileFromPath( + ["documents", "test-supamoto-device-credential.jsonld"], + "ascii" + ) + ); + file["issuer"] = daoCredsIssuerDid; + file["credentialSubject"]["id"] = ( + file["credentialSubject"]["id"] as string + ).replace("deviceId", id.toString()); + file["credentialSubject"]["certification"][ + "id" + ] = `https://ipfs.io/ipfs/${projectCertDoc}`; + let buff = Buffer.from(JSON.stringify(file)); + deviceCreds = ( + await customQueries.cellnode.uploadWeb3Doc( + utils.common.generateId(12), + "application/ld+json", + buff.toString("base64"), + undefined, + chainNetwork + ) + ).cid; + + console.log({ deviceCreds }); + if (!deviceCreds) throw new Error("error saving device creds file"); + + const res = await Entity1.CreateEntityAssetSupamotoInstance( + assetCollectionDid, + id, + i + 1, + deviceCreds, + dids.emergingDao + ); + const nftAssetDid = utils.common.getValueFromEvents( + res, + "wasm", + "token_id" + ); + console.log({ nftAssetDid }); + assetInstanceDids.push(nftAssetDid); + return res; + } + ) + ); + test("Logging all nft assets created", async () => { + console.log({ assetInstanceDids }); + expect(true).toBeTruthy(); + }); + }); diff --git a/assets/documents/test-supamoto-claims.jsonld b/assets/documents/test-supamoto-claims.jsonld index 17e0c44d..feb9ff44 100644 --- a/assets/documents/test-supamoto-claims.jsonld +++ b/assets/documents/test-supamoto-claims.jsonld @@ -14,11 +14,10 @@ "description": "Amount of Carbon Emissions reduced through the use of an energy-efficient clean cookstove." }, "submissions": { - "maximum": 100, - "startDate": "20-Jan-2023", - "endDate": "22-Feb-2026" + "maximum": null, + "startDate": "", + "endDate": "" } } - ], - "headlineMetric": "did:ixo:entity:abc123" + ] } diff --git a/assets/documents/test-supamoto-device-credential.jsonld b/assets/documents/test-supamoto-device-credential.jsonld index 0673d38e..eb1f7e93 100644 --- a/assets/documents/test-supamoto-device-credential.jsonld +++ b/assets/documents/test-supamoto-device-credential.jsonld @@ -26,7 +26,7 @@ }, "manufacturer": { "name": "Mimi Moto BV", - "country": "China", + "country": "CN", "date": "2019-2022" }, "certification": { diff --git a/assets/documents/test-supamoto-tags.jsonld b/assets/documents/test-supamoto-tags.jsonld index f6cc4a02..340201fd 100644 --- a/assets/documents/test-supamoto-tags.jsonld +++ b/assets/documents/test-supamoto-tags.jsonld @@ -9,15 +9,15 @@ "ddoTags": [ { "category": "Asset Type", - "tags": "Rights", - "color": "A11C43", - "image": "rights.svg" + "tags": [ + "Rights" + ] }, { "category": "Token Type", - "tags": "Carbon", - "color": "ED9526", - "image": "carbon.svg" + "tags": [ + "Carbon" + ] } ] } diff --git a/assets/documents/test-supamoto-token-metadata.json b/assets/documents/test-supamoto-token-metadata.json index ebf31f00..dd208dd7 100644 --- a/assets/documents/test-supamoto-token-metadata.json +++ b/assets/documents/test-supamoto-token-metadata.json @@ -1,14 +1,14 @@ { "id": "{id}#1", "type": "ImpactToken", - "name": "SupaMoto", + "name": "SupaMoto Genesis", "tokenName": "SupaMoto NFT", "decimals": 1, - "description": "SupaMoto NFT Malawi Collection", + "description": "SupaMoto Genesis Collection", "image": "imageLink", "properties": { - "denom": "SUPAMOTO", + "denom": "SUPAMOTO1", "icon": "iconLink", - "maxSupply": "1600" + "maxSupply": "600" } } diff --git a/package.json b/package.json index a6667100..a087d5d5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ixo/impactxclient-sdk", - "version": "1.0.0", + "version": "1.0.1", "description": "One ixo client to rule them all, One ixo client to find, One ixo client to bring them all, and in impact bind them", "author": "Ixo ", "homepage": "https://github.com/ixofoundation/ixo-MultiClient-SDK#readme", @@ -33,7 +33,8 @@ "test": "jest __tests__/index.spec.ts --forceExit", "test:query": "jest __tests__/index.query.spec.ts --forceExit", "test:watch": "jest --watch", - "test:debug": "node --inspect node_modules/.bin/jest --runInBand" + "test:debug": "node --inspect node_modules/.bin/jest --runInBand", + "test:setup": "jest __tests__/setup/index.setup.spec.ts --forceExit" }, "publishConfig": { "access": "public" diff --git a/src/custom_queries/cellnode.ts b/src/custom_queries/cellnode.ts index b3c6b99c..b68fab56 100644 --- a/src/custom_queries/cellnode.ts +++ b/src/custom_queries/cellnode.ts @@ -1,6 +1,14 @@ import axios from "axios"; import { ChainNetwork } from "./chain.types"; +/** + * Sample: { + key: 'lt2nc8vwbsjlfwap84z', + contentType: 'application/ld+json', + data: 'eyJAY29udGV4dCI6eyJpeG8iOiJodHRwczovL3czaWQub3JnL2l4by9ucy9wcm90b2NvbC8iLCJAaWQiOiJAdHlwZSIsInR5cGUiOiJAdHlwZSIsIkBwcm90ZWN0ZWQiOnRydWV9LCJ0eXBlIjoiaXhvOmVudGl0eSNwYWdlIiwicGFnZSI6eyJpZCI6IklyQ2NKOGhsOHQiLCJ0eXBlIjoicGFyYWdyYXBoIiwiZGF0YSI6eyJ0ZXh0IjoiVGhlIEltcGFjdCBEQU8gY29vcGVyYXRpdmUgbWFrZXMgb3V0Y29tZXMtYmFzZWQgaW52ZXN0bWVudHMgaW50byBpbm5vdmF0aW9ucywgcHJvamVjdHMgYW5kIHZlbnR1cmVzIHRoYXQgY2FuIGRsZWl2ZXIgSW50ZXJuZXQgb2YgSW1wYWN0IHNvbHV0aW9ucy4gTWVtYmVycyBvZiB0aGUgREFPIGFyZSBwaW9uZWVyaW5nIGlubm92YXRvcnMsIGludmVzdG9ycywgYnVpbGRlcnMsIGFuZCBpbXBsZW1lbnRvcnMgd2hvIGNvbnRyaWJ1dGUgY2FwaXRhbCwgd29yaywgb3Blbi1zb3VyY2Ugc29mdHdhcmUsIGFuZCBtYXJrZXQgYWNjZXNzIG9wcG9ydHVuaXRpZXMuIFRoZSBEQU8gdHJlYXN1cnkgcHJvdmlkZXMgZmluYW5jaW5nIGZvciB0aGUgZWNvc3lzdGVtIGJ5IGdyb3dpbmcgYSBwb3J0Zm9saW8gb2YgYXNzZXRzIGFuZCBieSBnZW5lcmF0aW5nIHJldmVudWVzIGZyb20gaXRzIGludmVzdG1lbnRzLiBUaGUgREFPIFRva2VucyByZXByZXNlbnQgZWFjaCBtZW1iZXIncyBwYXJ0aWNpcGF0aW9uIHNoYXJlIGluIHRoZSB0cmVhc3VyeSB0aGF0IGNhbiBiZSBleGNoYW5nZWQgYWZ0ZXIgdGhlIERBTyBicmVha3MgZXZlbi4gTW9yZSByZWNlbnQgaW52ZXN0b3JzIHJlY2l2ZSBhIGxpcXVpZGF0aW9uIHByZWZlcmVuY2UuIn19fQ==', + url: 'https://devnet-cellnode.ixo.earth/public/lt2nc8vwbsjlfwap84z' + } + */ export type CellnodePublicResource = { key: string; contentType: string; // mimetype @@ -8,6 +16,14 @@ export type CellnodePublicResource = { url: string; }; +/** + * Sample: { + cid: 'bafkreieevelc4vmpo6p2lsqu2zgiuc3xatxuzoquwtvqea6zabufbxmwiu', + name: 'atJywpxoUyHx', + ipfs: 'bafkreieevelc4vmpo6p2lsqu2zgiuc3xatxuzoquwtvqea6zabufbxmwiu.ipfs.w3s.link', + url: 'https://bafkreieevelc4vmpo6p2lsqu2zgiuc3xatxuzoquwtvqea6zabufbxmwiu.ipfs.w3s.link' + } + */ export type CellnodeWeb3Resource = { cid: string; name: string; diff --git a/src/custom_queries/contract.constants.ts b/src/custom_queries/contract.constants.ts index 6681035d..c317699b 100644 --- a/src/custom_queries/contract.constants.ts +++ b/src/custom_queries/contract.constants.ts @@ -3,162 +3,162 @@ export const contracts = [ name: "cw721", path: ["contracts", "ixo", "cw721.wasm"], category: "ixo", - code: { devnet: 1, testnet: 1 }, + code: { devnet: 1, testnet: 1, mainnet: 1 }, }, { name: "ixo1155", path: ["contracts", "ixo", "ixo1155.wasm"], category: "ixo", - code: { devnet: 2, testnet: 2 }, + code: { devnet: 2, testnet: 2, mainnet: 2 }, }, { name: "dao_core", path: ["contracts", "daodao", "dao_core.wasm"], category: "daodao", - code: { devnet: 3, testnet: 3 }, + code: { devnet: 3, testnet: 3, mainnet: 3 }, }, { name: "cw_admin_factory", path: ["contracts", "daodao", "cw_admin_factory.wasm"], category: "daodao", - code: { devnet: 4, testnet: 4 }, + code: { devnet: 4, testnet: 4, mainnet: 4 }, }, { name: "cw_fund_distributor", path: ["contracts", "daodao", "cw_fund_distributor.wasm"], category: "daodao", - code: { devnet: 5, testnet: 5 }, + code: { devnet: 5, testnet: 5, mainnet: 5 }, }, { name: "cw_payroll_factory", path: ["contracts", "daodao", "cw_payroll_factory.wasm"], category: "daodao", - code: { devnet: 6, testnet: 6 }, + code: { devnet: 6, testnet: 6, mainnet: 6 }, }, { name: "cw_token_swap", path: ["contracts", "daodao", "cw_token_swap.wasm"], category: "daodao", - code: { devnet: 7, testnet: 7 }, + code: { devnet: 7, testnet: 7, mainnet: 7 }, }, { name: "cw_vesting", path: ["contracts", "daodao", "cw_vesting.wasm"], category: "daodao", - code: { devnet: 8, testnet: 8 }, + code: { devnet: 8, testnet: 8, mainnet: 8 }, }, { name: "dao_migrator", path: ["contracts", "daodao", "dao_migrator.wasm"], category: "daodao", - code: { devnet: 9, testnet: 9 }, + code: { devnet: 9, testnet: 9, mainnet: 9 }, }, { name: "dao_pre_propose_approval_single", path: ["contracts", "daodao", "dao_pre_propose_approval_single.wasm"], category: "daodao", - code: { devnet: 10, testnet: 10 }, + code: { devnet: 10, testnet: 10, mainnet: 10 }, }, { name: "dao_pre_propose_approver", path: ["contracts", "daodao", "dao_pre_propose_approver.wasm"], category: "daodao", - code: { devnet: 11, testnet: 11 }, + code: { devnet: 11, testnet: 11, mainnet: 11 }, }, { name: "dao_pre_propose_multiple", path: ["contracts", "daodao", "dao_pre_propose_multiple.wasm"], category: "daodao", - code: { devnet: 12, testnet: 12 }, + code: { devnet: 12, testnet: 12, mainnet: 12 }, }, { name: "dao_pre_propose_single", path: ["contracts", "daodao", "dao_pre_propose_single.wasm"], category: "daodao", - code: { devnet: 13, testnet: 13 }, + code: { devnet: 13, testnet: 13, mainnet: 13 }, }, { name: "dao_proposal_condorcet", path: ["contracts", "daodao", "dao_proposal_condorcet.wasm"], category: "daodao", - code: { devnet: 14, testnet: 14 }, + code: { devnet: 14, testnet: 14, mainnet: 14 }, }, { name: "dao_proposal_multiple", path: ["contracts", "daodao", "dao_proposal_multiple.wasm"], category: "daodao", - code: { devnet: 15, testnet: 15 }, + code: { devnet: 15, testnet: 15, mainnet: 15 }, }, { name: "dao_proposal_single", path: ["contracts", "daodao", "dao_proposal_single.wasm"], category: "daodao", - code: { devnet: 16, testnet: 16 }, + code: { devnet: 16, testnet: 16, mainnet: 16 }, }, { name: "cw20_stake", path: ["contracts", "daodao", "cw20_stake.wasm"], category: "daodao", - code: { devnet: 17, testnet: 17 }, + code: { devnet: 17, testnet: 17, mainnet: 17 }, }, { name: "cw20_stake_external_rewards", path: ["contracts", "daodao", "cw20_stake_external_rewards.wasm"], category: "daodao", - code: { devnet: 18, testnet: 18 }, + code: { devnet: 18, testnet: 18, mainnet: 18 }, }, { name: "cw20_stake_reward_distributor", path: ["contracts", "daodao", "cw20_stake_reward_distributor.wasm"], category: "daodao", - code: { devnet: 19, testnet: 19 }, + code: { devnet: 19, testnet: 19, mainnet: 19 }, }, { name: "dao_voting_cw4", path: ["contracts", "daodao", "dao_voting_cw4.wasm"], category: "daodao", - code: { devnet: 20, testnet: 20 }, + code: { devnet: 20, testnet: 20, mainnet: 20 }, }, { name: "dao_voting_cw20_staked", path: ["contracts", "daodao", "dao_voting_cw20_staked.wasm"], category: "daodao", - code: { devnet: 21, testnet: 21 }, + code: { devnet: 21, testnet: 21, mainnet: 21 }, }, { name: "dao_voting_cw721_staked", path: ["contracts", "daodao", "dao_voting_cw721_staked.wasm"], category: "daodao", - code: { devnet: 22, testnet: 22 }, + code: { devnet: 22, testnet: 22, mainnet: 22 }, }, { name: "dao_voting_native_staked", path: ["contracts", "daodao", "dao_voting_native_staked.wasm"], category: "daodao", - code: { devnet: 23, testnet: 23 }, + code: { devnet: 23, testnet: 23, mainnet: 23 }, }, { name: "cw4_group", path: ["contracts", "cosmwasm", "cw4_group.wasm"], category: "daodao", - code: { devnet: 24, testnet: 24 }, + code: { devnet: 24, testnet: 24, mainnet: 24 }, }, { name: "cw20_base", path: ["contracts", "cosmwasm", "cw20_base.wasm"], category: "daodao", - code: { devnet: 25, testnet: 25 }, + code: { devnet: 25, testnet: 25, mainnet: 25 }, }, { name: "cw721_base", path: ["contracts", "cosmwasm", "cw721_base.wasm"], category: "daodao", - code: { devnet: 26, testnet: 26 }, + code: { devnet: 26, testnet: 26, mainnet: 26 }, }, { name: "wasmswap", path: ["contracts", "wasmswap", "wasmswap.wasm"], category: "daodao", - code: { devnet: 27, testnet: 27 }, + code: { devnet: 27, testnet: 27, mainnet: 27 }, }, ]; diff --git a/src/stargate_client/customRegistries.ts b/src/stargate_client/customRegistries.ts index 3b5ba6eb..15856606 100644 --- a/src/stargate_client/customRegistries.ts +++ b/src/stargate_client/customRegistries.ts @@ -2,6 +2,9 @@ import { GeneratedType, Registry } from "@cosmjs/proto-signing"; import { ixo, cosmwasm, cosmos, ibc, ica } from "../codegen"; export const defaultRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [ + // tx + ["/cosmos.tx.v1beta1.Tx", cosmos.tx.v1beta1.Tx], + // base ["/cosmos.base.v1beta1.Coin", cosmos.base.v1beta1.Coin], diff --git a/src/utils/did.ts b/src/utils/did.ts index b4f04d32..a5ffb796 100644 --- a/src/utils/did.ts +++ b/src/utils/did.ts @@ -14,3 +14,13 @@ export function generateSecpDid(pubkey: string | Uint8Array, prefix?: string) { const did = base58btcCode + encodedpubKey; return "did:" + (prefix || "x") + ":" + did; } + +/** + * Return a did with ixo method did and cosmwasm namespace, for the purpose + * to have iid docs onchain for corresponding cosmwasm addresses + * + * @param address bech32 encoded address, eg: ixo1r3us73z564xxxcessqmc4h0dwh8j4z6sxn2730ag09mq87hlrkzqrg8clc + */ +export function generateCosmwasmDid(address: string) { + return `did:ixo:cosmwasm:${address}`; +}