@openzeppelin/miden-multisig-client 0.13.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account/builder.test.d.ts +2 -0
- package/dist/account/builder.test.d.ts.map +1 -0
- package/dist/account/builder.test.js +39 -0
- package/dist/account/builder.test.js.map +1 -0
- package/dist/multisig/proposal/execution.d.ts +2 -1
- package/dist/multisig/proposal/execution.d.ts.map +1 -1
- package/dist/multisig/proposal/execution.js +11 -0
- package/dist/multisig/proposal/execution.js.map +1 -1
- package/dist/multisig.d.ts +2 -1
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +20 -1
- package/dist/multisig.js.map +1 -1
- package/dist/proposal/exported.d.ts +12 -0
- package/dist/proposal/exported.d.ts.map +1 -0
- package/dist/proposal/exported.js +88 -0
- package/dist/proposal/exported.js.map +1 -0
- package/dist/proposal/metadata.d.ts +15 -0
- package/dist/proposal/metadata.d.ts.map +1 -0
- package/dist/proposal/metadata.js +212 -0
- package/dist/proposal/metadata.js.map +1 -0
- package/dist/signer.test.js +32 -26
- package/dist/signer.test.js.map +1 -1
- package/dist/transaction/p2id.interop.test.d.ts +2 -0
- package/dist/transaction/p2id.interop.test.d.ts.map +1 -0
- package/dist/transaction/p2id.interop.test.js +36 -0
- package/dist/transaction/p2id.interop.test.js.map +1 -0
- package/dist/transaction/p2id.test.d.ts +2 -0
- package/dist/transaction/p2id.test.d.ts.map +1 -0
- package/dist/transaction/p2id.test.js +138 -0
- package/dist/transaction/p2id.test.js.map +1 -0
- package/dist/transaction/rpoRandomCoin.d.ts +7 -0
- package/dist/transaction/rpoRandomCoin.d.ts.map +1 -0
- package/dist/transaction/rpoRandomCoin.js +17 -0
- package/dist/transaction/rpoRandomCoin.js.map +1 -0
- package/dist/transaction/rpoRandomCoin.test.d.ts +2 -0
- package/dist/transaction/rpoRandomCoin.test.d.ts.map +1 -0
- package/dist/transaction/rpoRandomCoin.test.js +52 -0
- package/dist/transaction/rpoRandomCoin.test.js.map +1 -0
- package/dist/utils/state-validation.d.ts +5 -0
- package/dist/utils/state-validation.d.ts.map +1 -0
- package/dist/utils/state-validation.js +30 -0
- package/dist/utils/state-validation.js.map +1 -0
- package/dist/utils/validation.d.ts +6 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +52 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +2 -2
- package/src/multisig/proposal/execution.ts +44 -0
- package/src/multisig.ts +24 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
const { mockHashElements, seedFelts } = vi.hoisted(() => {
|
|
3
|
+
const seedFelts = [
|
|
4
|
+
{ id: 'seed-0' },
|
|
5
|
+
{ id: 'seed-1' },
|
|
6
|
+
{ id: 'seed-2' },
|
|
7
|
+
{ id: 'seed-3' },
|
|
8
|
+
];
|
|
9
|
+
return {
|
|
10
|
+
mockHashElements: vi.fn().mockReturnValue({ id: 'drawn-word' }),
|
|
11
|
+
seedFelts,
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
vi.mock('@miden-sdk/miden-sdk', () => {
|
|
15
|
+
class Felt {
|
|
16
|
+
value;
|
|
17
|
+
constructor(value) {
|
|
18
|
+
this.value = value;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
class FeltArray {
|
|
22
|
+
values;
|
|
23
|
+
constructor(values) {
|
|
24
|
+
this.values = values;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
Felt,
|
|
29
|
+
FeltArray,
|
|
30
|
+
Rpo256: {
|
|
31
|
+
hashElements: mockHashElements,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
import { RpoRandomCoin } from './rpoRandomCoin.js';
|
|
36
|
+
describe('RpoRandomCoin', () => {
|
|
37
|
+
it('drawWord hashes seed felts plus four zero felts', () => {
|
|
38
|
+
const seed = { toFelts: () => seedFelts };
|
|
39
|
+
const coin = new RpoRandomCoin(seed);
|
|
40
|
+
const drawn = coin.drawWord();
|
|
41
|
+
expect(drawn).toEqual({ id: 'drawn-word' });
|
|
42
|
+
expect(mockHashElements).toHaveBeenCalledTimes(1);
|
|
43
|
+
const [feltArrayArg] = mockHashElements.mock.calls[0];
|
|
44
|
+
const values = feltArrayArg.values;
|
|
45
|
+
expect(values).toHaveLength(8);
|
|
46
|
+
expect(values.slice(0, 4)).toEqual(seedFelts);
|
|
47
|
+
for (const felt of values.slice(4)) {
|
|
48
|
+
expect(felt.value).toBe(0n);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=rpoRandomCoin.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpoRandomCoin.test.js","sourceRoot":"","sources":["../../src/transaction/rpoRandomCoin.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAGlD,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;IACtD,MAAM,SAAS,GAAG;QAChB,EAAE,EAAE,EAAE,QAAQ,EAAE;QAChB,EAAE,EAAE,EAAE,QAAQ,EAAE;QAChB,EAAE,EAAE,EAAE,QAAQ,EAAE;QAChB,EAAE,EAAE,EAAE,QAAQ,EAAE;KACjB,CAAC;IAEF,OAAO;QACL,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC;QAC/D,SAAS;KACV,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,IAAI,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACnC,MAAM,IAAI;QACC,KAAK,CAAS;QAEvB,YAAY,KAAa;YACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;KACF;IAED,MAAM,SAAS;QACJ,MAAM,CAAY;QAE3B,YAAY,MAAiB;YAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACvB,CAAC;KACF;IAED,OAAO;QACL,IAAI;QACJ,SAAS;QACT,MAAM,EAAE;YACN,YAAY,EAAE,gBAAgB;SAC/B;KACF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,IAAI,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,EAAqB,CAAC;QAC7D,MAAM,IAAI,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAE9B,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,gBAAgB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAElD,MAAM,CAAC,YAAY,CAAC,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAA4B,CAAC;QACjF,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;QAEnC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC9C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YACnC,MAAM,CAAE,IAA0B,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Account, AccountId, WebClient } from '@miden-sdk/miden-sdk';
|
|
2
|
+
export declare function fetchNormalizedOnChainCommitment(webClient: WebClient, accountId: AccountId): Promise<string>;
|
|
3
|
+
export declare function verifyStateCommitmentAgainstOnChain(accountId: AccountId, stateCommitmentHex: string, onChainCommitmentHex: string): void;
|
|
4
|
+
export declare function verifyDeserializedAccountMatchesState(accountId: AccountId, stateCommitmentHex: string, account: Account, onChainCommitmentHex: string): void;
|
|
5
|
+
//# sourceMappingURL=state-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-validation.d.ts","sourceRoot":"","sources":["../../src/utils/state-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAmB1E,wBAAsB,gCAAgC,CACpD,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,wBAAgB,mCAAmC,CACjD,SAAS,EAAE,SAAS,EACpB,kBAAkB,EAAE,MAAM,EAC1B,oBAAoB,EAAE,MAAM,GAC3B,IAAI,CAON;AAED,wBAAgB,qCAAqC,CACnD,SAAS,EAAE,SAAS,EACpB,kBAAkB,EAAE,MAAM,EAC1B,OAAO,EAAE,OAAO,EAChB,oBAAoB,EAAE,MAAM,GAC3B,IAAI,CAgBN"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { normalizeHexWord } from './encoding.js';
|
|
2
|
+
function asAccountDetailsReader(webClient) {
|
|
3
|
+
const candidate = webClient;
|
|
4
|
+
if (typeof candidate.getAccountDetails !== 'function') {
|
|
5
|
+
throw new Error('WebClient does not expose getAccountDetails');
|
|
6
|
+
}
|
|
7
|
+
return candidate;
|
|
8
|
+
}
|
|
9
|
+
export async function fetchNormalizedOnChainCommitment(webClient, accountId) {
|
|
10
|
+
const fetchedAccount = await asAccountDetailsReader(webClient).getAccountDetails(accountId);
|
|
11
|
+
return normalizeHexWord(fetchedAccount.commitment().toHex());
|
|
12
|
+
}
|
|
13
|
+
export function verifyStateCommitmentAgainstOnChain(accountId, stateCommitmentHex, onChainCommitmentHex) {
|
|
14
|
+
const normalizedStateCommitment = normalizeHexWord(stateCommitmentHex);
|
|
15
|
+
if (normalizedStateCommitment !== onChainCommitmentHex) {
|
|
16
|
+
throw new Error(`PSM state commitment does not match on-chain commitment for account ${accountId.toString()}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function verifyDeserializedAccountMatchesState(accountId, stateCommitmentHex, account, onChainCommitmentHex) {
|
|
20
|
+
if (account.id().toString().toLowerCase() !== accountId.toString().toLowerCase()) {
|
|
21
|
+
throw new Error(`PSM state account ID ${account.id().toString()} does not match requested account ID ${accountId.toString()}`);
|
|
22
|
+
}
|
|
23
|
+
const normalizedStateCommitment = normalizeHexWord(stateCommitmentHex);
|
|
24
|
+
const normalizedAccountCommitment = normalizeHexWord(account.commitment().toHex());
|
|
25
|
+
if (normalizedAccountCommitment !== normalizedStateCommitment) {
|
|
26
|
+
throw new Error(`PSM state commitment does not match deserialized account commitment for account ${accountId.toString()}`);
|
|
27
|
+
}
|
|
28
|
+
verifyStateCommitmentAgainstOnChain(accountId, normalizedStateCommitment, onChainCommitmentHex);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=state-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-validation.js","sourceRoot":"","sources":["../../src/utils/state-validation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAUjD,SAAS,sBAAsB,CAAC,SAAoB;IAClD,MAAM,SAAS,GAAG,SAAqD,CAAC;IACxE,IAAI,OAAO,SAAS,CAAC,iBAAiB,KAAK,UAAU,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,SAAiC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,SAAoB,EACpB,SAAoB;IAEpB,MAAM,cAAc,GAAG,MAAM,sBAAsB,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC5F,OAAO,gBAAgB,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,mCAAmC,CACjD,SAAoB,EACpB,kBAA0B,EAC1B,oBAA4B;IAE5B,MAAM,yBAAyB,GAAG,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;IACvE,IAAI,yBAAyB,KAAK,oBAAoB,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CACb,uEAAuE,SAAS,CAAC,QAAQ,EAAE,EAAE,CAC9F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qCAAqC,CACnD,SAAoB,EACpB,kBAA0B,EAC1B,OAAgB,EAChB,oBAA4B;IAE5B,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QACjF,MAAM,IAAI,KAAK,CACb,wBAAwB,OAAO,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,wCAAwC,SAAS,CAAC,QAAQ,EAAE,EAAE,CAC9G,CAAC;IACJ,CAAC;IAED,MAAM,yBAAyB,GAAG,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;IACvE,MAAM,2BAA2B,GAAG,gBAAgB,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;IACnF,IAAI,2BAA2B,KAAK,yBAAyB,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CACb,mFAAmF,SAAS,CAAC,QAAQ,EAAE,EAAE,CAC1G,CAAC;IACJ,CAAC;IAED,mCAAmC,CAAC,SAAS,EAAE,yBAAyB,EAAE,oBAAoB,CAAC,CAAC;AAClG,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Account, type AccountId } from '@miden-sdk/miden-sdk';
|
|
2
|
+
export declare function isMissingAccountRecordError(error: unknown): boolean;
|
|
3
|
+
export declare function getOnChainCommitment(rpcEndpoint: string, accountId: AccountId): Promise<string>;
|
|
4
|
+
export declare function validateStateCommitmentMatchesOnChain(accountId: AccountId, stateCommitmentHex: string, onChainCommitmentHex: string): void;
|
|
5
|
+
export declare function validateAccountMatchesState(accountId: AccountId, stateCommitmentHex: string, account: Account): void;
|
|
6
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAuB,MAAM,sBAAsB,CAAC;AAGzF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAMnE;AAED,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,wBAAgB,qCAAqC,CACnD,SAAS,EAAE,SAAS,EACpB,kBAAkB,EAAE,MAAM,EAC1B,oBAAoB,EAAE,MAAM,GAC3B,IAAI,CAON;AAED,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,SAAS,EACpB,kBAAkB,EAAE,MAAM,EAC1B,OAAO,EAAE,OAAO,GACf,IAAI,CAyBN"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Endpoint, RpcClient } from '@miden-sdk/miden-sdk';
|
|
2
|
+
import { normalizeHexWord } from './encoding.js';
|
|
3
|
+
export function isMissingAccountRecordError(error) {
|
|
4
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5
|
+
return (message.includes('No account header record found for given ID') ||
|
|
6
|
+
message.includes('null pointer passed to rust'));
|
|
7
|
+
}
|
|
8
|
+
export async function getOnChainCommitment(rpcEndpoint, accountId) {
|
|
9
|
+
const rpcClient = new RpcClient(new Endpoint(rpcEndpoint));
|
|
10
|
+
try {
|
|
11
|
+
const fetchedAccount = await rpcClient.getAccountDetails(accountId);
|
|
12
|
+
if (!fetchedAccount) {
|
|
13
|
+
throw new Error('No account header record found for given ID');
|
|
14
|
+
}
|
|
15
|
+
return normalizeHexWord(fetchedAccount.commitment().toHex());
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
19
|
+
if (message.includes('null pointer passed to rust')) {
|
|
20
|
+
throw new Error('No account header record found for given ID');
|
|
21
|
+
}
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function validateStateCommitmentMatchesOnChain(accountId, stateCommitmentHex, onChainCommitmentHex) {
|
|
26
|
+
const normalizedStateCommitment = normalizeHexWord(stateCommitmentHex);
|
|
27
|
+
if (normalizedStateCommitment !== onChainCommitmentHex) {
|
|
28
|
+
throw new Error(`PSM state commitment does not match on-chain commitment for account ${accountId.toString()}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function validateAccountMatchesState(accountId, stateCommitmentHex, account) {
|
|
32
|
+
try {
|
|
33
|
+
const accountIdString = account.id().toString().toLowerCase();
|
|
34
|
+
const requestedIdString = accountId.toString().toLowerCase();
|
|
35
|
+
if (accountIdString !== requestedIdString) {
|
|
36
|
+
throw new Error(`PSM state account ID ${accountIdString} does not match requested account ID ${requestedIdString}`);
|
|
37
|
+
}
|
|
38
|
+
const normalizedStateCommitment = normalizeHexWord(stateCommitmentHex);
|
|
39
|
+
const normalizedAccountCommitment = normalizeHexWord(account.commitment().toHex());
|
|
40
|
+
if (normalizedAccountCommitment !== normalizedStateCommitment) {
|
|
41
|
+
throw new Error(`PSM state commitment does not match deserialized account commitment for account ${requestedIdString}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
46
|
+
if (message.includes('null pointer passed to rust')) {
|
|
47
|
+
throw new Error('No account header record found for given ID');
|
|
48
|
+
}
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openzeppelin/miden-multisig-client",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.1",
|
|
4
4
|
"description": "TypeScript SDK for Miden multisig accounts with PSM integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@miden-sdk/miden-sdk": "^0.13.0",
|
|
30
30
|
"@noble/hashes": "^2.0.1",
|
|
31
|
-
"@openzeppelin/psm-client": "^0.13.
|
|
31
|
+
"@openzeppelin/psm-client": "^0.13.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"typescript": "^5.7.2",
|
|
@@ -91,6 +91,50 @@ export async function executeProposalWorkflow(
|
|
|
91
91
|
await submitTransaction(params.webClient, params.accountId, finalRequest);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
|
|
95
|
+
export async function createTransactionProposalRequest(
|
|
96
|
+
params: ExecuteProposalWorkflowParams,
|
|
97
|
+
): Promise<TransactionRequest> {
|
|
98
|
+
ensureProposalReady(
|
|
99
|
+
params.proposal,
|
|
100
|
+
params.threshold,
|
|
101
|
+
params.getEffectiveThreshold,
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const isSwitchPsm = params.proposal.metadata.proposalType === 'switch_psm';
|
|
105
|
+
const executionSource = await resolveExecutionSource(
|
|
106
|
+
params.psm,
|
|
107
|
+
params.accountId,
|
|
108
|
+
params.proposal,
|
|
109
|
+
isSwitchPsm,
|
|
110
|
+
);
|
|
111
|
+
const executionData = prepareExecutionData(executionSource.txSummaryBase64);
|
|
112
|
+
|
|
113
|
+
const adviceMap = buildCosignerAdviceMap(
|
|
114
|
+
params.proposal,
|
|
115
|
+
params.signerCommitments,
|
|
116
|
+
executionData.txCommitmentHex,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
if (!isSwitchPsm && executionSource.delta) {
|
|
120
|
+
await appendPsmAckAdvice(
|
|
121
|
+
params.psm,
|
|
122
|
+
executionSource.delta,
|
|
123
|
+
params.psmCommitment,
|
|
124
|
+
params.psmPublicKey,
|
|
125
|
+
params.signatureScheme,
|
|
126
|
+
executionData.txCommitmentHex,
|
|
127
|
+
adviceMap,
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return await buildFinalRequest(
|
|
132
|
+
params,
|
|
133
|
+
executionData.saltHex,
|
|
134
|
+
adviceMap,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
94
138
|
function ensureProposalReady(
|
|
95
139
|
proposal: TransactionProposal,
|
|
96
140
|
defaultThreshold: number,
|
package/src/multisig.ts
CHANGED
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
toPsmSignature,
|
|
44
44
|
buildPsmSignatureFromSigner,
|
|
45
45
|
} from './multisig/signing.js';
|
|
46
|
-
import { executeProposalWorkflow } from './multisig/proposal/execution.js';
|
|
46
|
+
import { createTransactionProposalRequest, executeProposalWorkflow } from './multisig/proposal/execution.js';
|
|
47
47
|
|
|
48
48
|
export interface AccountState {
|
|
49
49
|
accountId: string;
|
|
@@ -680,6 +680,29 @@ export class Multisig {
|
|
|
680
680
|
return JSON.stringify(exported, null, 2);
|
|
681
681
|
}
|
|
682
682
|
|
|
683
|
+
async createTransactionProposalRequest(commitment: string): Promise<TransactionRequest> {
|
|
684
|
+
|
|
685
|
+
const proposal = this.proposals.get(commitment);
|
|
686
|
+
if (!proposal) {
|
|
687
|
+
throw new Error(`Proposal not found: ${commitment}`);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const request = await createTransactionProposalRequest({
|
|
691
|
+
proposal,
|
|
692
|
+
accountId: this._accountId,
|
|
693
|
+
threshold: this.threshold,
|
|
694
|
+
signerCommitments: this.signerCommitments,
|
|
695
|
+
psmCommitment: this.psmCommitment,
|
|
696
|
+
psmPublicKey: this.psmPublicKey,
|
|
697
|
+
signatureScheme: this.signatureScheme,
|
|
698
|
+
getEffectiveThreshold: (proposalType) => this.getEffectiveThreshold(proposalType),
|
|
699
|
+
psm: this.psm,
|
|
700
|
+
webClient: this.webClient,
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
return request;
|
|
704
|
+
}
|
|
705
|
+
|
|
683
706
|
importTransactionProposal(json: string): TransactionProposalResult {
|
|
684
707
|
const exported: ExportedTransactionProposal = JSON.parse(json);
|
|
685
708
|
|