diff --git a/examples/integration-scripts/challenge.ts b/examples/integration-scripts/challenge.ts index 0c9215e0..b8398d42 100644 --- a/examples/integration-scripts/challenge.ts +++ b/examples/integration-scripts/challenge.ts @@ -1,24 +1,13 @@ -import { strict as assert } from "assert"; +import { strict as assert } from "assert" +import signify from "signify-ts" -let signify: any; const url = "http://127.0.0.1:3901" const boot_url = "http://127.0.0.1:3903" -// @ts-ignore -import('signify-ts').then( - (module) => { - signify = module - signify.ready().then(() => { - console.log("*** Starting CHALLENGE test ***"); - run().then(() => { - console.log("*** Test complete ***") - }); - }); - } -) +await run() async function run() { - + await signify.ready() // Boot two clients const bran1 = signify.randomPasscode() const bran2 = signify.randomPasscode() @@ -40,13 +29,14 @@ async function run() { assert.equal(challenge1_big.words.length, 24) // Create two identifiers, one for each client - let op1 = await client1.identifiers().create('alice', { + let icpResult1 = await client1.identifiers().create('alice', { toad: 3, wits: [ "BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha", "BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM", "BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX"] }) + let op1 = await icpResult1.op() while (!op1["done"] ) { op1 = await client1.operations().get(op1.name); await new Promise(resolve => setTimeout(resolve, 1000)); @@ -55,13 +45,14 @@ async function run() { await client1.identifiers().addEndRole("alice", 'agent', client1!.agent!.pre) console.log("Alice's AID:", aid1.i) - let op2 = await client2.identifiers().create('bob', { + let icpResult2 = await client2.identifiers().create('bob', { toad: 3, wits: [ "BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha", "BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM", "BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX"] }) + let op2 = await icpResult2.op() while (!op2["done"] ) { op2 = await client2.operations().get(op2.name); await new Promise(resolve => setTimeout(resolve, 1000)); diff --git a/examples/integration-scripts/credentials.ts b/examples/integration-scripts/credentials.ts index 772aea7f..ad28c718 100644 --- a/examples/integration-scripts/credentials.ts +++ b/examples/integration-scripts/credentials.ts @@ -1,24 +1,13 @@ -import { strict as assert } from "assert"; +import { strict as assert } from "assert" +import signify from "signify-ts" -let signify: any; const url = "http://127.0.0.1:3901" const boot_url = "http://127.0.0.1:3903" -// @ts-ignore -import('signify-ts').then( - (module) => { - signify = module - signify.ready().then(() => { - console.log("*** Starting CREDENTIALS test ***"); - run().then(() => { - console.log("*** Test complete ***") - }); - }); - } -) +await run() async function run() { - + await signify.ready() // Boot three clients const bran1 = signify.randomPasscode() const bran2 = signify.randomPasscode() diff --git a/examples/integration-scripts/delegation.ts b/examples/integration-scripts/delegation.ts index 8563fde1..3c6dc821 100644 --- a/examples/integration-scripts/delegation.ts +++ b/examples/integration-scripts/delegation.ts @@ -1,24 +1,13 @@ -import { strict as assert } from "assert"; +import { strict as assert } from "assert" +import signify from "signify-ts" -let signify: any; const url = "http://127.0.0.1:3901" const boot_url = "http://127.0.0.1:3903" -// @ts-ignore -import('signify-ts').then( - (module) => { - signify = module - signify.ready().then(() => { - console.log("*** Starting DELEGATION test ***"); - run().then(() => { - console.log("*** Test complete ***") - }); - }); - } -) +await run() async function run() { - + await signify.ready() // Boot two clients const bran1 = signify.randomPasscode() const bran2 = signify.randomPasscode() diff --git a/examples/integration-scripts/multisig.ts b/examples/integration-scripts/multisig.ts index 9f185cd1..273ffce8 100644 --- a/examples/integration-scripts/multisig.ts +++ b/examples/integration-scripts/multisig.ts @@ -1,24 +1,13 @@ -import { strict as assert } from "assert"; +import { strict as assert } from "assert" +import signify from "signify-ts" -let signify: any; const url = "http://127.0.0.1:3901" const boot_url = "http://127.0.0.1:3903" -// @ts-ignore -import('signify-ts').then( - (module) => { - signify = module - signify.ready().then(() => { - console.log("*** Starting MULTISIG test ***"); - run().then(() => { - console.log("*** Test complete ***") - }); - }); - } -) +await run() async function run() { - + await signify.ready() // Boot three clients const bran1 = signify.randomPasscode() const bran2 = signify.randomPasscode() @@ -40,8 +29,8 @@ async function run() { console.log("Client 3 connected. Client AID:",state3.controller.state.i,"Agent AID: ", state3.agent.i) - // Create two identifiers, one for each client - let icpResult1 = client1.identifiers().create('multisig1', { + // Create three identifiers, one for each client + let icpResult1 = client1.identifiers().create('member1', { toad: 3, wits: [ "BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha", @@ -53,11 +42,11 @@ async function run() { op1 = await client1.operations().get(op1.name); await new Promise(resolve => setTimeout(resolve, 1000)); } - const aid1 = await client1.identifiers().get("multisig1") - await client1.identifiers().addEndRole("multisig1", 'agent', client1!.agent!.pre) - console.log("Multisig1's AID:", aid1.prefix) + let aid1 = await client1.identifiers().get("member1") + await client1.identifiers().addEndRole("member1", 'agent', client1!.agent!.pre) + console.log("Member1's AID:", aid1.prefix) - let icpResult2 = client2.identifiers().create('multisig2', { + let icpResult2 = client2.identifiers().create('member2', { toad: 3, wits: [ "BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha", @@ -69,11 +58,11 @@ async function run() { op2 = await client2.operations().get(op2.name); await new Promise(resolve => setTimeout(resolve, 1000)); } - const aid2 = await client2.identifiers().get("multisig2") - await client2.identifiers().addEndRole("multisig2", 'agent', client2!.agent!.pre) - console.log("Multisig2's AID:", aid2.prefix) + let aid2 = await client2.identifiers().get("member2") + await client2.identifiers().addEndRole("member2", 'agent', client2!.agent!.pre) + console.log("Member2's AID:", aid2.prefix) - let icpResult3 = client3.identifiers().create('multisig3', { + let icpResult3 = client3.identifiers().create('member3', { toad: 3, wits: [ "BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha", @@ -85,53 +74,53 @@ async function run() { op3 = await client3.operations().get(op3.name); await new Promise(resolve => setTimeout(resolve, 1000)); } - const aid3 = await client3.identifiers().get("multisig3") - await client3.identifiers().addEndRole("multisig3", 'agent', client3!.agent!.pre) - console.log("Multisig3's AID:", aid3.prefix) + let aid3 = await client3.identifiers().get("member3") + await client3.identifiers().addEndRole("member3", 'agent', client3!.agent!.pre) + console.log("Member3's AID:", aid3.prefix) - // Exchenge OOBIs + // Exchange OOBIs console.log("Resolving OOBIs") - let oobi1 = await client1.oobis().get("multisig1","agent") - let oobi2 = await client2.oobis().get("multisig2","agent") - let oobi3 = await client3.oobis().get("multisig3","agent") + let oobi1 = await client1.oobis().get("member1","agent") + let oobi2 = await client2.oobis().get("member2","agent") + let oobi3 = await client3.oobis().get("member3","agent") - op1 = await client1.oobis().resolve(oobi2.oobis[0],"multisig2") + op1 = await client1.oobis().resolve(oobi2.oobis[0],"member2") while (!op1["done"]) { op1 = await client1.operations().get(op1.name); await new Promise(resolve => setTimeout(resolve, 1000)); } - op1 = await client1.oobis().resolve(oobi3.oobis[0],"multisig3") + op1 = await client1.oobis().resolve(oobi3.oobis[0],"member3") while (!op1["done"]) { op1 = await client1.operations().get(op1.name); await new Promise(resolve => setTimeout(resolve, 1000)); } - console.log("Multisig1 resolved 2 OOBIs") + console.log("Member1 resolved 2 OOBIs") - op2 = await client2.oobis().resolve(oobi1.oobis[0],"multisig1") + op2 = await client2.oobis().resolve(oobi1.oobis[0],"member1") while (!op2["done"]) { op2 = await client2.operations().get(op2.name); await new Promise(resolve => setTimeout(resolve, 1000)); } - op2 = await client2.oobis().resolve(oobi3.oobis[0],"multisig3") + op2 = await client2.oobis().resolve(oobi3.oobis[0],"member3") while (!op2["done"]) { op2 = await client2.operations().get(op2.name); await new Promise(resolve => setTimeout(resolve, 1000)); } - console.log("Multisig2 resolved 2 OOBIs") + console.log("Member2 resolved 2 OOBIs") - op3 = await client3.oobis().resolve(oobi1.oobis[0],"multisig1") + op3 = await client3.oobis().resolve(oobi1.oobis[0],"member1") while (!op3["done"]) { op3 = await client3.operations().get(op3.name); await new Promise(resolve => setTimeout(resolve, 1000)); } - op3 = await client3.oobis().resolve(oobi2.oobis[0],"multisig2") + op3 = await client3.oobis().resolve(oobi2.oobis[0],"member2") while (!op3["done"]) { op3 = await client3.operations().get(op3.name); await new Promise(resolve => setTimeout(resolve, 1000)); } - console.log("Multisig3 resolved 2 OOBIs") + console.log("Member3 resolved 2 OOBIs") - // Create a multisig identifier + // First member start the creation of a multisig identifier let rstates = [aid1["state"], aid2["state"], aid3["state"]] let states = rstates icpResult1 = client1.identifiers().create("multisig",{ @@ -161,20 +150,35 @@ async function run() { let smids = states.map((state) => state['i']) let recp = [aid2["state"], aid3["state"]].map((state) => state['i']) - await client1.exchanges().send("multisig1", "multisig", aid1, "/multisig/icp", + await client1.exchanges().send("member1", "multisig", aid1, "/multisig/icp", {'gid': serder.pre, smids: smids, rmids: smids}, embeds, recp) - console.log("Multisig1 joined multisig waiting for others...") + console.log("Member1 initiated multisig, waiting for others to join...") + + // Second member check notifications and join the multisig + let msgSaid = "" + while (msgSaid=="") { + let notifications = await client2.notifications().list() + for (let notif of notifications.notes){ + if (notif.a.r == '/multisig/icp') { + msgSaid = notif.a.d + await client2.notifications().mark(notif.i) + console.log("Member2 received exchange message to join multisig") + } + } + await new Promise(resolve => setTimeout(resolve, 1000)); + } + let res = await client2.groups().getRequest(msgSaid) + let exn = res[0].exn + let icp = exn.e.icp + icpResult2 = client2.identifiers().create("multisig",{ algo: signify.Algos.group, mhab: aid2, - isith: 3, - nsith: 3, - toad: 3, - wits: [ - "BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha", - "BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM", - "BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX"], + isith: icp.kt, + nsith: icp.nt, + toad: parseInt(icp.bt), + wits: icp.b, states: states, rstates: rstates }) @@ -189,23 +193,38 @@ async function run() { icp: [serder, atc], } - smids = states.map((state) => state['i']) + smids = exn.a.smids recp = [aid1["state"], aid3["state"]].map((state) => state['i']) - await client2.exchanges().send("multisig2", "multisig", aid2, "/multisig/icp", + await client2.exchanges().send("member2", "multisig", aid2, "/multisig/icp", {'gid': serder.pre, smids: smids, rmids: smids}, embeds, recp) - console.log("Multisig2 joined multisig waiting for others...") + console.log("Member2 joined multisig, waiting for others...") + + // Third member check notifications and join the multisig + msgSaid = "" + while (msgSaid=="") { + let notifications = await client3.notifications().list() + for (let notif of notifications.notes){ + if (notif.a.r == '/multisig/icp') { + msgSaid = notif.a.d + await client3.notifications().mark(notif.i) + console.log("Member3 received exchange message to join multisig") + } + } + await new Promise(resolve => setTimeout(resolve, 1000)); + } + + res = await client3.groups().getRequest(msgSaid) + exn = res[0].exn + icp = exn.e.icp icpResult3 = client3.identifiers().create("multisig",{ algo: signify.Algos.group, mhab: aid3, - isith: 3, - nsith: 3, - toad: 3, - wits: [ - "BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha", - "BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM", - "BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX"], + isith: icp.kt, + nsith: icp.nt, + toad: parseInt(icp.bt), + wits: icp.b, states: states, rstates: rstates }) @@ -220,13 +239,14 @@ async function run() { icp: [serder, atc], } - smids = states.map((state) => state['i']) + smids = exn.a.smids recp = [aid1["state"], aid2["state"]].map((state) => state['i']) - await client3.exchanges().send("multisig3", "multisig", aid3, "/multisig/icp", + await client3.exchanges().send("member3", "multisig", aid3, "/multisig/icp", {'gid': serder.pre, smids: smids, rmids: smids}, embeds, recp) - console.log("Multisig3 joined multisig waiting for others...") + console.log("Member3 joined, multisig waiting for others...") + // Check for completion while (!op1["done"]) { op1 = await client1.operations().get(op1.name); await new Promise(resolve => setTimeout(resolve, 1000)); @@ -243,21 +263,310 @@ async function run() { const identifiers1 = await client1.identifiers().list() assert.equal(identifiers1.aids.length, 2) - assert.equal(identifiers1.aids[0].name, "multisig") - assert.equal(identifiers1.aids[1].name, "multisig1") + assert.equal(identifiers1.aids[0].name, "member1") + assert.equal(identifiers1.aids[1].name, "multisig") const identifiers2 = await client2.identifiers().list() assert.equal(identifiers2.aids.length, 2) - assert.equal(identifiers2.aids[0].name, "multisig") - assert.equal(identifiers2.aids[1].name, "multisig2") + assert.equal(identifiers2.aids[0].name, "member2") + assert.equal(identifiers2.aids[1].name, "multisig") const identifiers3 = await client3.identifiers().list() assert.equal(identifiers3.aids.length, 2) - assert.equal(identifiers3.aids[0].name, "multisig") - assert.equal(identifiers3.aids[1].name, "multisig3") + assert.equal(identifiers3.aids[0].name, "member3") + assert.equal(identifiers3.aids[1].name, "multisig") + + console.log("Client 1 managed AIDs:", identifiers1.aids[0].name, identifiers1.aids[1].name) + console.log("Client 2 managed AIDs:", identifiers2.aids[0].name, identifiers2.aids[1].name) + console.log("Client 3 managed AIDs:", identifiers3.aids[0].name, identifiers3.aids[1].name) + + + // MultiSig Interaction + + // Member1 initiates an interaction event + let data = {"i": "EE77q3_zWb5ojgJr-R1vzsL5yiL4Nzm-bfSOQzQl02dy"} + let eventResponse1 = await client1.identifiers().interact("multisig", data) + op1 = await eventResponse1.op() + serder = eventResponse1.serder + sigs = eventResponse1.sigs + sigers = sigs.map((sig: any) => new signify.Siger({qb64: sig})) + + ims = signify.d(signify.messagize(serder, sigers)) + atc = ims.substring(serder.size) + let xembeds = { + ixn: [serder, atc], + } + + smids = states.map((state) => state['i']) + recp = [aid2["state"], aid3["state"]].map((state) => state['i']) + + await client1.exchanges().send("member1", "multisig", aid1, "/multisig/ixn", + {'gid': serder.pre, smids: smids, rmids: smids}, xembeds, recp) + console.log("Member1 initiates interaction event, waiting for others to join...") + + // Member2 check for notifications and join the interaction event + msgSaid = "" + while (msgSaid=="") { + let notifications = await client2.notifications().list() + for (let notif of notifications.notes){ + if (notif.a.r == '/multisig/ixn') { + msgSaid = notif.a.d + await client2.notifications().mark(notif.i) + console.log("Member2 received exchange message to join the interaction event") + } + } + await new Promise(resolve => setTimeout(resolve, 1000)); + } + res = await client2.groups().getRequest(msgSaid) + exn = res[0].exn + let ixn = exn.e.ixn + data = ixn.a + + icpResult2 = await client2.identifiers().interact("multisig",data) + op2 = await icpResult2.op() + serder = icpResult2.serder + sigs = icpResult2.sigs + sigers = sigs.map((sig: any) => new signify.Siger({qb64: sig})) + + ims = signify.d(signify.messagize(serder, sigers)) + atc = ims.substring(serder.size) + xembeds = { + ixn: [serder, atc], + } + + smids = exn.a.smids + recp = [aid1["state"], aid3["state"]].map((state) => state['i']) + + await client2.exchanges().send("member2", "multisig", aid2, "/multisig/ixn", + {'gid': serder.pre, smids: smids, rmids: smids}, xembeds, recp) + console.log("Member2 joins interaction event, waiting for others...") + + // Member3 check for notifications and join the interaction event + msgSaid = "" + while (msgSaid=="") { + let notifications = await client3.notifications().list() + for (let notif of notifications.notes){ + if (notif.a.r == '/multisig/ixn') { + msgSaid = notif.a.d + await client3.notifications().mark(notif.i) + console.log("Member3 received exchange message to join the interaction event") + } + } + await new Promise(resolve => setTimeout(resolve, 1000)); + } + res = await client3.groups().getRequest(msgSaid) + exn = res[0].exn + ixn = exn.e.ixn + data = ixn.a + + icpResult3 = await client3.identifiers().interact("multisig",data) + op3 = await icpResult3.op() + serder = icpResult3.serder + sigs = icpResult3.sigs + sigers = sigs.map((sig: any) => new signify.Siger({qb64: sig})) + + ims = signify.d(signify.messagize(serder, sigers)) + atc = ims.substring(serder.size) + xembeds = { + ixn: [serder, atc], + } + + smids = exn.a.smids + recp = [aid1["state"], aid2["state"]].map((state) => state['i']) + + await client3.exchanges().send("member3", "multisig", aid3, "/multisig/ixn", + {'gid': serder.pre, smids: smids, rmids: smids}, xembeds, recp) + console.log("Member3 joins interaction event, waiting for others...") + + // Check for completion + while (!op1["done"]) { + op1 = await client1.operations().get(op1.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + while (!op2["done"]) { + op2 = await client2.operations().get(op2.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + while (!op3["done"]) { + op3 = await client3.operations().get(op3.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + console.log("Multisig interaction completed!") + + // Members agree out of band to rotate keys + console.log("Members agree out of band to rotate keys") + icpResult1 = await client1.identifiers().rotate('member1') + op1 = await icpResult1.op() + while (!op1["done"]) { + op1 = await client1.operations().get(op1.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + aid1 = await client1.identifiers().get("member1") - console.log("Client 1 identifiers:", identifiers1.aids[0].name, identifiers1.aids[1].name) - console.log("Client 2 identifiers:", identifiers2.aids[0].name, identifiers2.aids[1].name) - console.log("Client 3 identifiers:", identifiers3.aids[0].name, identifiers3.aids[1].name) + console.log("Member1 rotated keys") + icpResult2 = await client2.identifiers().rotate('member2') + op2 = await icpResult2.op() + while (!op2["done"]) { + op2 = await client2.operations().get(op2.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + aid2 = await client2.identifiers().get("member2") + console.log("Member2 rotated keys") + icpResult3 = await client3.identifiers().rotate('member3') + op3 = await icpResult3.op() + while (!op3["done"]) { + op3 = await client3.operations().get(op3.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + aid3 = await client3.identifiers().get("member3") + console.log("Member3 rotated keys") + + // Update new key states + op1 = await client1.keyStates().query(aid2.prefix,1) + while (!op1["done"]) { + op1 = await client1.operations().get(op1.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + let aid2State = op1["response"] + op1 = await client1.keyStates().query(aid3.prefix,1) + while (!op1["done"]) { + op1 = await client1.operations().get(op1.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + let aid3State = op1["response"] + + op2 = await client2.keyStates().query(aid3.prefix,1) + while (!op2["done"]) { + op2 = await client2.operations().get(op2.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + op2 = await client2.keyStates().query(aid1.prefix,1) + while (!op2["done"]) { + op2 = await client2.operations().get(op2.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + let aid1State = op2["response"] + op3 = await client3.keyStates().query(aid1.prefix,1) + while (!op3["done"]) { + op3 = await client3.operations().get(op3.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + op3 = await client3.keyStates().query(aid2.prefix,1) + while (!op3["done"]) { + op3 = await client3.operations().get(op3.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + + rstates = [aid1State, aid2State, aid3State] + states = rstates + + // Multisig Rotation + + // Member1 initiates a rotation event + eventResponse1 = await client1.identifiers().rotate("multisig",{states: states,rstates: rstates}) + op1 = await eventResponse1.op() + serder = eventResponse1.serder + sigs = eventResponse1.sigs + sigers = sigs.map((sig: any) => new signify.Siger({qb64: sig})) + + ims = signify.d(signify.messagize(serder, sigers)) + atc = ims.substring(serder.size) + let rembeds = { + rot: [serder, atc], + } + + smids = states.map((state) => state['i']) + recp = [aid2State, aid3State].map((state) => state['i']) + + await client1.exchanges().send("member1", "multisig", aid1 , "/multisig/rot", + {'gid': serder.pre, smids: smids, rmids: smids}, rembeds, recp) + console.log("Member1 initiates rotation event, waiting for others to join...") + + // Member2 check for notifications and join the rotation event + msgSaid = "" + while (msgSaid=="") { + let notifications = await client2.notifications().list() + for (let notif of notifications.notes){ + if (notif.a.r == '/multisig/rot') { + msgSaid = notif.a.d + await client2.notifications().mark(notif.i) + console.log("Member2 received exchange message to join the rotation event") + } + } + await new Promise(resolve => setTimeout(resolve, 1000)); + } + + await new Promise(resolve => setTimeout(resolve, 5000)); + res = await client2.groups().getRequest(msgSaid) + exn = res[0].exn + + icpResult2 = await client2.identifiers().rotate("multisig",{states: states,rstates: rstates}) + op2 = await icpResult2.op() + serder = icpResult2.serder + sigs = icpResult2.sigs + sigers = sigs.map((sig: any) => new signify.Siger({qb64: sig})) + + ims = signify.d(signify.messagize(serder, sigers)) + atc = ims.substring(serder.size) + rembeds = { + rot: [serder, atc], + } + + smids = exn.a.smids + recp = [aid1State, aid3State].map((state) => state['i']) + + await client2.exchanges().send("member2", "multisig", aid2, "/multisig/ixn", + {'gid': serder.pre, smids: smids, rmids: smids}, rembeds, recp) + console.log("Member2 joins rotation event, waiting for others...") + + // Member3 check for notifications and join the rotation event + msgSaid = "" + while (msgSaid=="") { + let notifications = await client3.notifications().list(1) + for (let notif of notifications.notes){ + if (notif.a.r == '/multisig/rot') { + msgSaid = notif.a.d + await client3.notifications().mark(notif.i) + console.log("Member3 received exchange message to join the rotation event") + } + } + await new Promise(resolve => setTimeout(resolve, 1000)); + } + res = await client3.groups().getRequest(msgSaid) + exn = res[0].exn + + icpResult3 = await client3.identifiers().rotate("multisig",{states: states,rstates: rstates}) + op3 = await icpResult3.op() + serder = icpResult3.serder + sigs = icpResult3.sigs + sigers = sigs.map((sig: any) => new signify.Siger({qb64: sig})) + + ims = signify.d(signify.messagize(serder, sigers)) + atc = ims.substring(serder.size) + rembeds = { + rot: [serder, atc], + } + + smids = exn.a.smids + recp = [aid1State, aid2State].map((state) => state['i']) + + await client3.exchanges().send("member3", "multisig", aid3, "/multisig/ixn", + {'gid': serder.pre, smids: smids, rmids: smids}, rembeds, recp) + console.log("Member3 joins rotation event, waiting for others...") + + // Check for completion + while (!op1["done"]) { + op1 = await client1.operations().get(op1.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + while (!op2["done"]) { + op2 = await client2.operations().get(op2.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + while (!op3["done"]) { + op3 = await client3.operations().get(op3.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + console.log("Multisig rotation completed!") } \ No newline at end of file diff --git a/examples/integration-scripts/randy.ts b/examples/integration-scripts/randy.ts index 0ed53017..caa1ad7a 100644 --- a/examples/integration-scripts/randy.ts +++ b/examples/integration-scripts/randy.ts @@ -1,24 +1,13 @@ -import { strict as assert } from "assert"; +import { strict as assert } from "assert" +import signify from "signify-ts" -let signify: any; const url = "http://127.0.0.1:3901" const boot_url = "http://127.0.0.1:3903" -// @ts-ignore -import('signify-ts').then( - (module) => { - signify = module - signify.ready().then(() => { - console.log("*** Starting RANDY test ***"); - run().then(() => { - console.log("*** Test complete ***") - }); - }); - } -) +await run() async function run() { - + await signify.ready() // Boot client const bran1 = signify.randomPasscode() const client1 = new signify.SignifyClient(url, bran1, signify.Tier.low, boot_url); @@ -44,7 +33,8 @@ async function run() { assert.equal(aid.name, 'aid1') assert.equal(aid.prefix, icp.pre) - op = await client1.identifiers().interact("aid1", [icp.pre]) + icpResult = await client1.identifiers().interact("aid1", [icp.pre]) + op = await icpResult.op() assert.equal(op['done'], true) let ked = op['response'] let ixn = new signify.Serder(ked) @@ -59,7 +49,8 @@ async function run() { let log = await events.get(aid["prefix"]) assert.equal(log.length, 2) - op = await client1.identifiers().rotate('aid1') + icpResult = await client1.identifiers().rotate('aid1') + op = await icpResult.op() assert.equal(op['done'], true) ked = op['response'] let rot = new signify.Serder(ked) diff --git a/examples/integration-scripts/request-present.ts b/examples/integration-scripts/request-present.ts index 295e356c..3f4d0523 100644 --- a/examples/integration-scripts/request-present.ts +++ b/examples/integration-scripts/request-present.ts @@ -1,24 +1,13 @@ -import { strict as assert } from "assert"; +import { strict as assert } from "assert" +import signify from "signify-ts" -let signify: any; const url = "http://127.0.0.1:3901" const boot_url = "http://127.0.0.1:3903" -// @ts-ignore -import('signify-ts').then( - (module) => { - signify = module - signify.ready().then(() => { - console.log("*** Starting REQUEST-PRESENT test ***"); - run().then(() => { - console.log("*** Test complete ***") - }); - }); - } -) +await run() async function run() { - + await signify.ready() // Boot three clients const bran1 = signify.randomPasscode() const bran2 = signify.randomPasscode() diff --git a/examples/integration-scripts/salty.ts b/examples/integration-scripts/salty.ts index 4e1082cd..9a222489 100644 --- a/examples/integration-scripts/salty.ts +++ b/examples/integration-scripts/salty.ts @@ -1,24 +1,13 @@ -import { strict as assert } from "assert"; +import { strict as assert } from "assert" +import signify from "signify-ts" -let signify: any; const url = "http://127.0.0.1:3901" const boot_url = "http://127.0.0.1:3903" -// @ts-ignore -import('signify-ts').then( - (module) => { - signify = module - signify.ready().then(() => { - console.log("*** Starting SALTY test ***"); - run().then(() => { - console.log("*** Test complete ***") - }); - }); - } -) +await run() async function run() { - + await signify.ready() // Boot client const bran1 = signify.randomPasscode() const client1 = new signify.SignifyClient(url, bran1, signify.Tier.low, boot_url); @@ -89,7 +78,8 @@ async function run() { aid = aids.aids[0] assert.equal(aid.name, 'aid3') - op = await client1.identifiers().rotate('aid1') + icpResult = await client1.identifiers().rotate('aid1') + op = await icpResult.op() assert.equal(op['done'], true) let ked = op['response'] let rot = new signify.Serder(ked) @@ -100,7 +90,8 @@ async function run() { assert.equal(rot.verfers[0].qb64, 'DHgomzINlGJHr-XP3sv2ZcR9QsIEYS3LJhs4KRaZYKly') assert.equal(rot.digers[0].qb64, 'EJMovBlrBuD6BVeUsGSxLjczbLEbZU9YnTSud9K4nVzk') - op = await client1.identifiers().interact("aid1", [icp.pre]) + icpResult = await client1.identifiers().interact("aid1", [icp.pre]) + op = await icpResult.op() assert.equal(op['done'], true) ked = op['response'] let ixn = new signify.Serder(ked) diff --git a/examples/integration-scripts/tsconfig.node.json b/examples/integration-scripts/tsconfig.node.json index 61c424ba..b1035cbd 100644 --- a/examples/integration-scripts/tsconfig.node.json +++ b/examples/integration-scripts/tsconfig.node.json @@ -2,6 +2,7 @@ "compilerOptions": { "composite": true, "skipLibCheck": true, + "target": "ESNext", "module": "ESNext", "moduleResolution": "bundler", "allowSyntheticDefaultImports": true diff --git a/examples/integration-scripts/witness.ts b/examples/integration-scripts/witness.ts index c91dfeec..f542df91 100644 --- a/examples/integration-scripts/witness.ts +++ b/examples/integration-scripts/witness.ts @@ -1,25 +1,13 @@ // This scrip also work if you start keria with no config file with witness urls import { strict as assert } from "assert"; +import signify from "signify-ts"; -let signify: any; const url = "http://127.0.0.1:3901" const boot_url = "http://127.0.0.1:3903" -// @ts-ignore -import('signify-ts').then( - (module) => { - signify = module - signify.ready().then(() => { - console.log("*** Starting WITNESS test ***"); - run().then(() => { - console.log("*** Test complete ***") - }); - }); - } -) - +await run() async function run() { - + await signify.ready() // Boot client const bran1 = signify.randomPasscode() const client1 = new signify.SignifyClient(url, bran1, signify.Tier.low, boot_url); @@ -48,9 +36,44 @@ async function run() { op1 = await client1.operations().get(op1.name); await new Promise(resolve => setTimeout(resolve, 1000)); } - const aid1 = await client1.identifiers().get("aid1") + let aid1 = await client1.identifiers().get("aid1") console.log("AID:",aid1.prefix) assert.equal(aid1.state.b.length, 1) assert.equal(aid1.state.b[0], witness) + icpResult1 = await client1.identifiers().rotate('aid1') + op1 = await icpResult1.op() + while (!op1["done"] ) { + op1 = await client1.operations().get(op1.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + aid1 = await client1.identifiers().get("aid1") + assert.equal(aid1.state.b.length, 1) + assert.equal(aid1.state.b[0], witness) + + // Remove witness + icpResult1 = await client1.identifiers().rotate('aid1',{cuts: [witness]}) + + op1 = await icpResult1.op() + while (!op1["done"] ) { + op1 = await client1.operations().get(op1.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + aid1 = await client1.identifiers().get("aid1") + assert.equal(aid1.state.b.length, 0) + + // Add witness again + + icpResult1 = await client1.identifiers().rotate('aid1',{adds: [witness]}) + + op1 = await icpResult1.op() + while (!op1["done"] ) { + op1 = await client1.operations().get(op1.name); + await new Promise(resolve => setTimeout(resolve, 1000)); + } + aid1 = await client1.identifiers().get("aid1") + assert.equal(aid1.state.b.length, 1) + assert.equal(aid1.state.b.length, 1) + assert.equal(aid1.state.b[0], witness) + } \ No newline at end of file diff --git a/src/keri/app/signify.ts b/src/keri/app/signify.ts index 4c485faf..4c341805 100644 --- a/src/keri/app/signify.ts +++ b/src/keri/app/signify.ts @@ -24,7 +24,7 @@ export class CredentialTypes { static received = "received" } -/** Starte of the client */ +/** State of the client */ class State { agent: any | null controller: any | null @@ -430,7 +430,7 @@ export class SignifyClient { } /** - * Get groups resource + * Get exchange resource * @returns {Exchanges} */ exchanges(): Exchanges { @@ -479,7 +479,7 @@ export interface RotateIdentifierArgs { rstates?: any[] } -export class InceptionResult { +export class EventResult { private readonly _serder: Serder private readonly _sigs: string[] private readonly promise: Promise @@ -562,9 +562,9 @@ export class Identifier { * @async * @param {string} name Name or alias of the identifier * @param {CreateIdentiferArgs} [kargs] Optional parameters to create the identifier - * @returns {InceptionResult} The inception result + * @returns {EventResult} The inception result */ - create(name: string, kargs:CreateIdentiferArgs={}): InceptionResult { + create(name: string, kargs:CreateIdentiferArgs={}): EventResult { const algo = kargs.algo == undefined ? Algos.salty : kargs.algo @@ -666,7 +666,7 @@ export class Identifier { this.client.pidx = this.client.pidx + 1 let res = this.client.fetch("/identifiers", "POST", jsondata) - return new InceptionResult(serder, sigs, res) + return new EventResult(serder, sigs, res) } /** @@ -674,9 +674,9 @@ export class Identifier { * @async * @param {string} name Name or alias of the identifier * @param {any} [data] Option data to be anchored in the interaction event - * @returns {Promise} A promise to the long-running operation + * @returns {Promise} A promise to the interaction event result */ - async interact(name: string, data?: any): Promise { + async interact(name: string, data?: any): Promise { let hab = await this.get(name) let pre: string = hab.prefix @@ -697,8 +697,8 @@ export class Identifier { } jsondata[keeper.algo] = keeper.params() - let res = await this.client.fetch("/identifiers/" + name + "?type=ixn", "PUT", jsondata) - return await res.json() + let res = this.client.fetch("/identifiers/" + name + "?type=ixn", "PUT", jsondata) + return new EventResult(serder, sigs, res) } @@ -706,15 +706,14 @@ export class Identifier { * Generate a rotation event in a managed identifier * @param {string} name Name or alias of the identifier * @param {RotateIdentifierArgs} [kargs] Optional parameters requiered to generate the rotation event - * @returns {Promise} + * @returns {Promise} A promise to the rotation event result */ - async rotate(name: string, kargs: RotateIdentifierArgs={}): Promise { + async rotate(name: string, kargs: RotateIdentifierArgs={}): Promise { let transferable = kargs.transferable ?? true let ncode = kargs.ncode ?? MtrDex.Ed25519_Seed let ncount = kargs.ncount ?? 1 - let hab = await this.get(name) let pre = hab.prefix @@ -774,8 +773,8 @@ export class Identifier { } jsondata[keeper.algo] = keeper.params() - let res = await this.client.fetch("/identifiers/" + name, "PUT", jsondata) - return await res.json() + let res = this.client.fetch("/identifiers/" + name, "PUT", jsondata) + return new EventResult(serder, sigs, res) } /** @@ -1941,7 +1940,7 @@ export class Exchanges { } /** - * Send exn messaget to list of recipients + * Send exn messages to list of recipients * @async * @returns {Promise} A promise to the list of replay messages * @param name diff --git a/src/keri/core/eventing.ts b/src/keri/core/eventing.ts index 32e61ad8..58648b2c 100644 --- a/src/keri/core/eventing.ts +++ b/src/keri/core/eventing.ts @@ -148,10 +148,9 @@ export function rotate({ throw new Error(`Invalid member combination among cuts = ${cuts}, and adds = ${adds}.`) } - let newitsetdiff = new Set([...witset].filter(x => cutset.has(x))) - let newitset = new Set() - newitsetdiff.forEach(newitset.add, newitset) - addset.forEach(newitset.add, newitset) + let newitsetdiff = new Set(_wits) + _cuts.forEach(function(v) {newitsetdiff.delete(v) }) + let newitset = new Set(function*() { yield* newitsetdiff; yield* addset; }()) if (newitset.size != (witset.size - cutset.size + addset.size)) { throw new Error(`Invalid member combination among wits = ${wits}, cuts = ${cuts}, and adds = ${adds}.`)