@arxiumlabs/sdk 0.8.0 → 0.9.0
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/README.md +20 -4
- package/dist/actions.d.ts +24 -1
- package/dist/actions.js +28 -2
- package/dist/cli.js +18 -2
- package/dist/fees.js +1 -0
- package/dist/policy.d.ts +5 -1
- package/dist/policy.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ npm install -g @arxiumlabs/sdk # arx CLI
|
|
|
13
13
|
|
|
14
14
|
## Releasing
|
|
15
15
|
|
|
16
|
-
Bump `version` here, run the release checks, then push a `sdk-vX.Y.Z` tag. `.github/workflows/sdk.yml` publishes to npm through trusted publishing (no token)
|
|
16
|
+
Bump `version` here, run the release checks, then push a `sdk-vX.Y.Z` tag. `.github/workflows/sdk.yml` publishes to npm through trusted publishing (no token). It publishes without a provenance attestation while the repository is private, because npm accepts provenance only from public repositories.
|
|
17
17
|
|
|
18
18
|
```sh
|
|
19
19
|
cd Arxium && cargo test -p arxd-runtime writes_typescript_signed_action_fixtures && git diff --exit-code sdk/ts/fixtures
|
|
@@ -73,6 +73,18 @@ A co-signer should see what they're signing before they sign it. `decodePayload(
|
|
|
73
73
|
|
|
74
74
|
Set the resulting address as an admin role (genesis or `SetAdmin`) or as an asset issuer (`TransferIssuer`). To rotate members, move the role to a new multisig address.
|
|
75
75
|
|
|
76
|
+
### Atomic DvP (delivery versus payment)
|
|
77
|
+
|
|
78
|
+
`SettleDvp` swaps two assets between two parties in one action: both legs settle or neither does. Each leg is `"native"` (IUM) or `{ asset }` (an RWA asset, with its full compliance gates, or a token). The counterparty signs the order first, at its current nonce. The initiator then sends it and pays the fee:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
const order: DvpOrder = { give: { asset: bondRef }, giveAmount: 10n, counterparty: buyer, take: { asset: cashRef }, takeAmount: 500n, expiresAt: height + 100n };
|
|
82
|
+
const consent = await signDvpConsent(buyerKey, genesis, seller, order, buyerNonce); // on the buyer's machine
|
|
83
|
+
await rpc.sendAction({ privateKey: sellerKey, sender: seller, payload: encodeSettleDvp(order, consent) });
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Settling consumes the counterparty's nonce, so the consent can't be replayed, and any other action the counterparty sends first cancels it. The node refuses the order after height `expiresAt`. A multisig counterparty's members each sign `dvpConsentBytes(…)` and combine them with `multisigSignature`. A programmable-account counterparty is not supported yet.
|
|
87
|
+
|
|
76
88
|
### Programmable accounts
|
|
77
89
|
|
|
78
90
|
The SDK exports bounded account-policy codecs and stateful owner/session/guardian witness helpers. `arx multisig build|sign|combine|link` lets each member sign separately, for both immutable and stateful account addresses. To verify a historical action, `verifySignedAction` needs the proven pre-action policy for stateful witnesses, and `arx verify SIGNATURE --policy FILE` accepts that policy. See [the programmable-account guide](../../docs/Programmable_Accounts.md).
|
|
@@ -110,7 +122,7 @@ printf '%s' "$SEED_HEX" | arx keys import
|
|
|
110
122
|
arx keys show --key arxium-devnet-key-abc.json # no passphrase needed
|
|
111
123
|
|
|
112
124
|
arx sign transfer arx1recipient 1500000000 --key key.json # nonce fetched from --rpc
|
|
113
|
-
arx sign transfer arx1recipient 1500000000 --key key.json --nonce 7 #
|
|
125
|
+
arx sign transfer arx1recipient 1500000000 --key key.json --nonce 7 # skips the nonce lookup; still reads the genesis hash from --rpc
|
|
114
126
|
arx submit signed-action.json
|
|
115
127
|
arx send transfer arx1recipient 1500000000 --key key.json
|
|
116
128
|
|
|
@@ -125,7 +137,9 @@ arx query search arx1address
|
|
|
125
137
|
arx verify signature
|
|
126
138
|
```
|
|
127
139
|
|
|
128
|
-
|
|
140
|
+
`arx sign` always needs a reachable node. Every signature covers the chain's genesis hash (see Chain binding above), and `sign` reads it from `--rpc` (`GET /genesis-hash`) on every run. `--nonce` only skips the account-nonce lookup. There is no fully offline signing mode: with no node the command exits 1 with the fetch error.
|
|
141
|
+
|
|
142
|
+
Supported signed actions are `transfer`, `stake`, `unstake`, `join-validator`, `leave-validator`, `register-bls-key`, `authorize-operator`, `revoke-operator`, `grant-attestation`, `revoke-attestation`, `register-asset`, `issue-asset`, `transfer-asset`, `apply-attestor`, `block-attestor`, `propose-add-attestor`, `propose-remove-attestor`, `propose-unblock-attestor`, `vote`, `execute-proposal` and `settle-dvp`, plus the issuer, corporate-action and token commands below. Amount arguments are raw base-unit integers (IUM for ARX, the asset's smallest unit for an asset).
|
|
129
143
|
|
|
130
144
|
```sh
|
|
131
145
|
arx send apply-attestor "Arxium Bank" <owner>,<owner>,<owner> 2 <evidence-hash> <evidence-uri> # sender is the 2-of-N multisig; validators vote
|
|
@@ -154,6 +168,8 @@ arx send redeem-holders arxasset1... <height>
|
|
|
154
168
|
arx send split-asset arxasset1... <height> 2 1
|
|
155
169
|
arx send create-token ABC "Abc Token" 6 1000000 - mintable # <max-supply|-> mintable|fixed
|
|
156
170
|
arx send mint-token arxasset1... arx1to 100 # transfer-token, burn-token, renounce-mint
|
|
171
|
+
arx dvp-consent arx1seller arxasset1bond... 10 native 500 <expires-at-height> --key buyer.json # buyer signs; prints the "send" args
|
|
172
|
+
arx send settle-dvp arxasset1bond... 10 arx1buyer native 500 <expires-at-height> <buyer-signature> --key seller.json
|
|
157
173
|
|
|
158
174
|
arx query assets [arx1address] # all assets, or one account's balances
|
|
159
175
|
arx query asset arxasset1...
|
|
@@ -175,7 +191,7 @@ public entry point and checks the CLI version; it makes no chain calls.
|
|
|
175
191
|
|
|
176
192
|
Publication runs only for an approved `sdk-vX.Y.Z` tag matching package.json.
|
|
177
193
|
The publish job builds its own checkout, checks the packed files and smoke-tests
|
|
178
|
-
the tarball, then publishes that exact tarball
|
|
194
|
+
the tarball, then publishes that exact tarball (no provenance while the repo is private). Existing npm
|
|
179
195
|
versions cannot be replaced. npm trusted-publisher configuration and release
|
|
180
196
|
authorization are still required; a passing package check is not publication
|
|
181
197
|
or on-chain compatibility proof.
|
package/dist/actions.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { POLICY_VARIANT } from "./policy.js";
|
|
1
|
+
import { POLICY_VARIANT, type SpendAsset } from "./policy.js";
|
|
2
2
|
/** These indices are ActionPayload's positional bincode discriminants. Never derive them. */
|
|
3
3
|
export declare const ACTION_VARIANT: {
|
|
4
4
|
readonly transfer: 0;
|
|
@@ -39,6 +39,7 @@ export declare const ACTION_VARIANT: {
|
|
|
39
39
|
readonly executeProposal: 32;
|
|
40
40
|
readonly applyAttestor: 41;
|
|
41
41
|
readonly blockAttestor: 42;
|
|
42
|
+
readonly settleDvp: 43;
|
|
42
43
|
};
|
|
43
44
|
/** `ActionPayload::Token(TokenAction)` is variant 39; these are `TokenAction`'s own discriminants, written after it. */
|
|
44
45
|
export declare const TOKEN_ACTION = 39;
|
|
@@ -137,6 +138,28 @@ export declare function encodeRenounceMint(tokenRef: string): Uint8Array;
|
|
|
137
138
|
export declare function encodeApplyAttestor(name: string, owners: string[], threshold: number, evidenceHash: string, evidenceUri: string): Uint8Array;
|
|
138
139
|
/** Emergency stop: the sending attestor can no longer grant new attestations. Only a governance vote lifts it. */
|
|
139
140
|
export declare function encodeBlockAttestor(): Uint8Array;
|
|
141
|
+
/**
|
|
142
|
+
* Atomic delivery-versus-payment. The sender (initiator) delivers `giveAmount` of `give` to `counterparty`, who delivers
|
|
143
|
+
* `takeAmount` of `take` back, both legs or neither. `"native"` is IUM; `{ asset }` is an RWA asset or a token ref.
|
|
144
|
+
*/
|
|
145
|
+
export type DvpOrder = {
|
|
146
|
+
give: SpendAsset;
|
|
147
|
+
giveAmount: bigint;
|
|
148
|
+
counterparty: string;
|
|
149
|
+
take: SpendAsset;
|
|
150
|
+
takeAmount: bigint;
|
|
151
|
+
expiresAt: bigint;
|
|
152
|
+
};
|
|
153
|
+
/** `DvpTerms.domain`: no `ActionPayload` can start with it, so a consent never doubles as an ordinary action signature. */
|
|
154
|
+
export declare const DVP_DOMAIN = 4294967295;
|
|
155
|
+
/**
|
|
156
|
+
* What the counterparty signs, mirroring `dvp_consent(…).signing_bytes`: the order, bound to the genesis hash and the
|
|
157
|
+
* counterparty's current nonce, which settling consumes. Sending any other action first cancels the consent. A multisig
|
|
158
|
+
* counterparty's members each sign these bytes and combine them with `multisigSignature`.
|
|
159
|
+
*/
|
|
160
|
+
export declare function dvpConsentBytes(genesis: Uint8Array, initiator: string, order: DvpOrder, counterpartyNonce: number | bigint): Uint8Array;
|
|
161
|
+
export declare function signDvpConsent(privateKey: CryptoKey, genesis: Uint8Array, initiator: string, order: DvpOrder, counterpartyNonce: number | bigint): Promise<string>;
|
|
162
|
+
export declare function encodeSettleDvp(order: DvpOrder, counterpartySignature: string): Uint8Array;
|
|
140
163
|
/** `GovernanceAction`'s own discriminants (after `SetChainParams` 0, `TreasurySpend` 1, `ResolveDispute` 2, `ReinstateValidator` 3). Only the attestor actions are encodable here. */
|
|
141
164
|
export declare const GOVERNANCE_ACTION: {
|
|
142
165
|
readonly addAttestor: 4;
|
package/dist/actions.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MULTISIG_TAG, decodeAddress, encodeAddress } from "./bech32.js";
|
|
2
2
|
import { Reader, Writer, asBuffer, fromHex, toHex } from "./bincode.js";
|
|
3
|
-
import { ACCOUNT_POLICY_ACTION, POLICY_VARIANT, encodeAccountPolicy, readAccountPolicy } from "./policy.js";
|
|
3
|
+
import { ACCOUNT_POLICY_ACTION, POLICY_VARIANT, encodeAccountPolicy, readAccountPolicy, readSpendAsset, writeSpendAsset } from "./policy.js";
|
|
4
4
|
/** These indices are ActionPayload's positional bincode discriminants. Never derive them. */
|
|
5
5
|
export const ACTION_VARIANT = {
|
|
6
6
|
transfer: 0, joinValidator: 1, leaveValidator: 2, stake: 3, unstake: 4, registerBlsKey: 6,
|
|
@@ -12,7 +12,7 @@ export const ACTION_VARIANT = {
|
|
|
12
12
|
snapshotHolders: 33, distributeToHolders: 34, redeemHolders: 35, splitAsset: 36,
|
|
13
13
|
verifyClaimProof: 37, setPrivateClaims: 38,
|
|
14
14
|
submitProposal: 30, voteProposal: 31, executeProposal: 32,
|
|
15
|
-
applyAttestor: 41, blockAttestor: 42,
|
|
15
|
+
applyAttestor: 41, blockAttestor: 42, settleDvp: 43,
|
|
16
16
|
};
|
|
17
17
|
/** `ActionPayload::Token(TokenAction)` is variant 39; these are `TokenAction`'s own discriminants, written after it. */
|
|
18
18
|
export const TOKEN_ACTION = 39;
|
|
@@ -79,6 +79,30 @@ export function encodeRenounceMint(tokenRef) { return token("renounceMint").stri
|
|
|
79
79
|
export function encodeApplyAttestor(name, owners, threshold, evidenceHash, evidenceUri) { return new Writer().varint(ACTION_VARIANT.applyAttestor).string(name).vec(owners, (w, o) => w.string(o)).u8(threshold).string(evidenceHash).string(evidenceUri).bytes(); }
|
|
80
80
|
/** Emergency stop: the sending attestor can no longer grant new attestations. Only a governance vote lifts it. */
|
|
81
81
|
export function encodeBlockAttestor() { return new Writer().varint(ACTION_VARIANT.blockAttestor).bytes(); }
|
|
82
|
+
/** `DvpTerms.domain`: no `ActionPayload` can start with it, so a consent never doubles as an ordinary action signature. */
|
|
83
|
+
export const DVP_DOMAIN = 0xffff_ffff;
|
|
84
|
+
/**
|
|
85
|
+
* What the counterparty signs, mirroring `dvp_consent(…).signing_bytes`: the order, bound to the genesis hash and the
|
|
86
|
+
* counterparty's current nonce, which settling consumes. Sending any other action first cancels the consent. A multisig
|
|
87
|
+
* counterparty's members each sign these bytes and combine them with `multisigSignature`.
|
|
88
|
+
*/
|
|
89
|
+
export function dvpConsentBytes(genesis, initiator, order, counterpartyNonce) {
|
|
90
|
+
const w = new Writer().varint(DVP_DOMAIN).string(initiator);
|
|
91
|
+
writeSpendAsset(w, order.give);
|
|
92
|
+
w.varint(order.giveAmount);
|
|
93
|
+
writeSpendAsset(w, order.take);
|
|
94
|
+
w.varint(order.takeAmount).varint(order.expiresAt);
|
|
95
|
+
return signingBytes(genesis, order.counterparty, counterpartyNonce, w.bytes());
|
|
96
|
+
}
|
|
97
|
+
export async function signDvpConsent(privateKey, genesis, initiator, order, counterpartyNonce) { return toHex(new Uint8Array(await crypto.subtle.sign("Ed25519", privateKey, asBuffer(dvpConsentBytes(genesis, initiator, order, counterpartyNonce))))); }
|
|
98
|
+
export function encodeSettleDvp(order, counterpartySignature) {
|
|
99
|
+
const w = new Writer().varint(ACTION_VARIANT.settleDvp);
|
|
100
|
+
writeSpendAsset(w, order.give);
|
|
101
|
+
w.varint(order.giveAmount).string(order.counterparty);
|
|
102
|
+
writeSpendAsset(w, order.take);
|
|
103
|
+
w.varint(order.takeAmount).varint(order.expiresAt).string(counterpartySignature);
|
|
104
|
+
return w.bytes();
|
|
105
|
+
}
|
|
82
106
|
/** `GovernanceAction`'s own discriminants (after `SetChainParams` 0, `TreasurySpend` 1, `ResolveDispute` 2, `ReinstateValidator` 3). Only the attestor actions are encodable here. */
|
|
83
107
|
export const GOVERNANCE_ACTION = { addAttestor: 4, removeAttestor: 5, unblockAttestor: 6 };
|
|
84
108
|
/** An active validator opens a vote. `addAttestor` needs the attestor's multisig address and its owners; applicants who are not validators use `encodeApplyAttestor`. A removal blocks that attestor's new grants while it runs. */
|
|
@@ -136,6 +160,7 @@ export function encodePayload({ name, input }) {
|
|
|
136
160
|
case "executeProposal": return encodeExecuteProposal(BigInt(input.proposal));
|
|
137
161
|
case "applyAttestor": return encodeApplyAttestor(input.name, input.owners, input.threshold, input.evidenceHash, input.evidenceUri);
|
|
138
162
|
case "blockAttestor": return encodeBlockAttestor();
|
|
163
|
+
case "settleDvp": return encodeSettleDvp({ give: input.give, giveAmount: BigInt(input.giveAmount), counterparty: input.counterparty, take: input.take, takeAmount: BigInt(input.takeAmount), expiresAt: BigInt(input.expiresAt) }, input.counterpartySignature);
|
|
139
164
|
case "createToken": return encodeCreateToken(input.symbol, input.name, input.decimals, BigInt(input.initialSupply), nullableBig(input.maxSupply), input.mintable);
|
|
140
165
|
case "mintToken": return encodeMintToken(input.token, input.to, BigInt(input.amount));
|
|
141
166
|
case "transferToken": return encodeTransferToken(input.token, input.to, BigInt(input.amount));
|
|
@@ -202,6 +227,7 @@ export function decodePayload(payload) {
|
|
|
202
227
|
executeProposal: () => ({ proposal: amount() }),
|
|
203
228
|
applyAttestor: () => ({ name: str(), owners: r.vec((rr) => rr.string()), threshold: r.u8(), evidenceHash: str(), evidenceUri: str() }),
|
|
204
229
|
blockAttestor: () => ({}),
|
|
230
|
+
settleDvp: () => ({ give: readSpendAsset(r), giveAmount: amount(), counterparty: str(), take: readSpendAsset(r), takeAmount: amount(), expiresAt: amount(), counterpartySignature: str() }),
|
|
205
231
|
createToken: () => ({ symbol: str(), name: str(), decimals: r.u8(), initialSupply: amount(), maxSupply: r.option(amount), mintable: r.bool() }),
|
|
206
232
|
mintToken: () => ({ token: str(), to: str(), amount: amount() }),
|
|
207
233
|
transferToken: () => ({ token: str(), to: str(), amount: amount() }),
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { readFile, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { basename } from "node:path";
|
|
4
4
|
import { stdin as input, stderr, stdout } from "node:process";
|
|
5
5
|
import { createPrivateKey, createPublicKey } from "node:crypto";
|
|
6
|
-
import { ArxiumRpc, RpcError, encodeApplyAttestor, encodeBlockAttestor, encodeExecuteProposal, encodeSubmitProposal, encodeVoteProposal, encodeAuthorizeOperator, encodeGrantAttestation, encodeIssueAsset, encodeRegisterAsset, encodeFreezeAsset, encodeSetHolderFrozen, encodeSetAssetLimits, encodeTransferAsset, encodeJoinValidator, encodeLeaveValidator, encodeRegisterBlsKey, encodeRevokeAttestation, encodeRevokeOperator, encodeStake, encodeTransfer, encodeUnstake, generateKey, isKeyFile, signAction, submitBody, unlockKey, verifyKeyFile, verifySignedAction, wrapPkcs8, encodeAddress, toHex, toKeyFile, PKCS8_ED25519_PREFIX, assemblePolicySignature, decodePayload, encodePayload, fromHex, multisigAddress, multisigSignature, signingBytes, asBuffer, ALL_ISSUER_CONTROLS, ISSUER_CONTROLS, bigintReplacer, encodeBurnAsset, encodeIssuerForcedTransfer, encodeRecoverHolder, encodeIssueAssetTo, encodeLockHolderAmount, encodeLockHolderAmountUntil, encodeLockIssuance, encodeTransferIssuer, encodeSetAssetMetadataUri, encodeSetPrivateClaims, encodeSnapshotHolders, encodeDistributeToHolders, encodeRedeemHolders, encodeSplitAsset, encodeCreateToken, encodeMintToken, encodeTransferToken, encodeBurnToken, encodeRenounceMint, } from "./index.js";
|
|
6
|
+
import { ArxiumRpc, RpcError, encodeApplyAttestor, encodeBlockAttestor, encodeExecuteProposal, encodeSubmitProposal, encodeVoteProposal, encodeAuthorizeOperator, encodeGrantAttestation, encodeIssueAsset, encodeRegisterAsset, encodeFreezeAsset, encodeSetHolderFrozen, encodeSetAssetLimits, encodeTransferAsset, encodeJoinValidator, encodeLeaveValidator, encodeRegisterBlsKey, encodeRevokeAttestation, encodeRevokeOperator, encodeStake, encodeTransfer, encodeUnstake, generateKey, isKeyFile, signAction, submitBody, unlockKey, verifyKeyFile, verifySignedAction, wrapPkcs8, encodeAddress, toHex, toKeyFile, PKCS8_ED25519_PREFIX, assemblePolicySignature, decodePayload, encodePayload, fromHex, multisigAddress, multisigSignature, signingBytes, asBuffer, ALL_ISSUER_CONTROLS, ISSUER_CONTROLS, bigintReplacer, encodeBurnAsset, encodeIssuerForcedTransfer, encodeRecoverHolder, encodeIssueAssetTo, encodeLockHolderAmount, encodeLockHolderAmountUntil, encodeLockIssuance, encodeTransferIssuer, encodeSetAssetMetadataUri, encodeSetPrivateClaims, encodeSnapshotHolders, encodeDistributeToHolders, encodeRedeemHolders, encodeSplitAsset, encodeCreateToken, encodeMintToken, encodeTransferToken, encodeBurnToken, encodeRenounceMint, encodeSettleDvp, signDvpConsent, } from "./index.js";
|
|
7
7
|
class UsageError extends Error {
|
|
8
8
|
}
|
|
9
9
|
function output(value, json) { stdout.write(!json && typeof value === "string" ? `${value}\n` : `${JSON.stringify(value, bigintReplacer, 2)}\n`); }
|
|
@@ -123,7 +123,9 @@ const USAGE = {
|
|
|
123
123
|
"split-asset": "<asset-ref> <snapshot-height> <numerator> <denominator>",
|
|
124
124
|
"create-token": "<symbol> <name> <decimals> <initial-supply> <max-supply|-> mintable|fixed", "mint-token": "<token-ref> <to> <amount>",
|
|
125
125
|
"transfer-token": "<token-ref> <to> <amount>", "burn-token": "<token-ref> <amount>", "renounce-mint": "<token-ref>",
|
|
126
|
+
"settle-dvp": "<give-asset-ref|native> <give-amount> <counterparty> <take-asset-ref|native> <take-amount> <expires-at-height> <counterparty-signature>",
|
|
126
127
|
};
|
|
128
|
+
const spendArg = (value) => value === "native" ? "native" : { asset: value };
|
|
127
129
|
function morePayload(action, args) {
|
|
128
130
|
const usage = USAGE[action] ?? throwUsage(`unsupported action: ${action}`);
|
|
129
131
|
const arg = (i) => args[i] ?? throwUsage(`${action} needs ${usage}`);
|
|
@@ -158,6 +160,7 @@ function morePayload(action, args) {
|
|
|
158
160
|
case "mint-token": return encodeMintToken(arg(0), arg(1), int(2));
|
|
159
161
|
case "transfer-token": return encodeTransferToken(arg(0), arg(1), int(2));
|
|
160
162
|
case "burn-token": return encodeBurnToken(arg(0), int(1));
|
|
163
|
+
case "settle-dvp": return encodeSettleDvp({ give: spendArg(arg(0)), giveAmount: int(1), counterparty: arg(2), take: spendArg(arg(3)), takeAmount: int(4), expiresAt: int(5) }, arg(6));
|
|
161
164
|
default: return encodeRenounceMint(arg(0));
|
|
162
165
|
}
|
|
163
166
|
}
|
|
@@ -177,7 +180,7 @@ async function main() {
|
|
|
177
180
|
return;
|
|
178
181
|
}
|
|
179
182
|
if (!command)
|
|
180
|
-
throwUsage("use: arx keys|sign|submit|send|query|verify");
|
|
183
|
+
throwUsage("use: arx keys|sign|submit|send|dvp-consent|query|verify");
|
|
181
184
|
if (command === "keys") {
|
|
182
185
|
const [operation, ...keyArgs] = rest;
|
|
183
186
|
if (operation === "new") {
|
|
@@ -284,6 +287,19 @@ async function main() {
|
|
|
284
287
|
}
|
|
285
288
|
throwUsage("use: arx multisig address|build|sign|combine|link");
|
|
286
289
|
}
|
|
290
|
+
// The counterparty's half of a DvP: sign the order at its current nonce. The initiator sends it with `arx send settle-dvp`.
|
|
291
|
+
if (command === "dvp-consent") {
|
|
292
|
+
const use = "dvp-consent needs <initiator> <give-asset-ref|native> <give-amount> <take-asset-ref|native> <take-amount> <expires-at-height>", [initiator, give, giveAmount, take, takeAmount, expiresAt] = rest;
|
|
293
|
+
if (!initiator || !give || !take || ![giveAmount, takeAmount, expiresAt].every((v) => /^\d+$/.test(v ?? "")))
|
|
294
|
+
throwUsage(use);
|
|
295
|
+
const { file, privateKey } = await loadKey(globals.key);
|
|
296
|
+
const nonce = globals.nonce ?? await rpc.account(file.address).then((account) => account.nonce, (error) => { if (error instanceof RpcError && error.status === 404)
|
|
297
|
+
return 0; throw error; });
|
|
298
|
+
const order = { give: spendArg(give), giveAmount: BigInt(giveAmount), counterparty: file.address, take: spendArg(take), takeAmount: BigInt(takeAmount), expiresAt: BigInt(expiresAt) };
|
|
299
|
+
const signature = await signDvpConsent(privateKey, await rpc.genesisHash(), initiator, order, nonce);
|
|
300
|
+
output({ counterparty: file.address, counterpartyNonce: nonce, signature, send: ["settle-dvp", give, giveAmount, file.address, take, takeAmount, expiresAt, signature] }, true);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
287
303
|
if (command === "sign" || command === "send") {
|
|
288
304
|
const action = rest[0] ?? throwUsage(`${command} needs an action`), { file, privateKey } = await loadKey(globals.key), encoded = payload(action, rest.slice(1));
|
|
289
305
|
if (command === "sign") {
|
package/dist/fees.js
CHANGED
|
@@ -20,6 +20,7 @@ const BASE_WEIGHT = {
|
|
|
20
20
|
[ACTION_VARIANT.transferIssuer]: 100, [ACTION_VARIANT.setAssetMetadataUri]: 100,
|
|
21
21
|
[ACTION_VARIANT.snapshotHolders]: 2_000, [ACTION_VARIANT.distributeToHolders]: 15_000,
|
|
22
22
|
[ACTION_VARIANT.redeemHolders]: 10_000, [ACTION_VARIANT.splitAsset]: 10_000,
|
|
23
|
+
[ACTION_VARIANT.settleDvp]: 350,
|
|
23
24
|
[ACTION_VARIANT.submitProposal]: 150, [ACTION_VARIANT.voteProposal]: 150, [ACTION_VARIANT.executeProposal]: 150,
|
|
24
25
|
5 /* SubmitEquivocationEvidence */: 2_000,
|
|
25
26
|
15 /* SubmitExecutionFault */: 500_000,
|
package/dist/policy.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Reader } from "./bincode.js";
|
|
1
|
+
import { Reader, Writer } from "./bincode.js";
|
|
2
2
|
export declare const ACCOUNT_POLICY_ACTION = 40;
|
|
3
3
|
export declare const POLICY_VARIANT: {
|
|
4
4
|
readonly setAccountPolicy: 0;
|
|
@@ -39,7 +39,11 @@ export type AccountPolicy = {
|
|
|
39
39
|
} | null;
|
|
40
40
|
};
|
|
41
41
|
export type PolicyMode = "owner" | "session" | "guardian";
|
|
42
|
+
declare function asset(w: Writer, a: SpendAsset): void;
|
|
43
|
+
export { asset as writeSpendAsset };
|
|
42
44
|
export declare function encodeAccountPolicy(name: keyof typeof POLICY_VARIANT, input: Record<string, any>): Uint8Array;
|
|
45
|
+
declare function readAsset(r: Reader): SpendAsset;
|
|
46
|
+
export { readAsset as readSpendAsset };
|
|
43
47
|
export declare function readAccountPolicy(r: Reader): {
|
|
44
48
|
name: keyof typeof POLICY_VARIANT;
|
|
45
49
|
input: Record<string, any>;
|
package/dist/policy.js
CHANGED
|
@@ -16,6 +16,7 @@ function asset(w, a) { if (a === "native")
|
|
|
16
16
|
w.varint(0);
|
|
17
17
|
else
|
|
18
18
|
w.varint(1).string(a.asset); }
|
|
19
|
+
export { asset as writeSpendAsset };
|
|
19
20
|
function recipients(w, list) { if (list.length > 64 || list.some((a, i) => i > 0 && list[i - 1] >= a))
|
|
20
21
|
throw new Error("recipients must be bounded, unique and sorted"); w.vec(list, (ww, a) => ww.string(a)); }
|
|
21
22
|
function session(w, s) { w.raw(key(s.publicKey)).varint(bounded(s.expiresAt, 64)); asset(w, s.asset); w.varint(bounded(s.allowance, 128)); recipients(w, s.recipients); }
|
|
@@ -56,6 +57,7 @@ function readThreshold(r) { return { threshold: r.u8(), members: r.vec(readKey)
|
|
|
56
57
|
function readAsset(r) { const tag = r.varint(); if (tag === 0n)
|
|
57
58
|
return "native"; if (tag === 1n)
|
|
58
59
|
return { asset: r.string() }; throw new Error("unknown spend asset"); }
|
|
60
|
+
export { readAsset as readSpendAsset };
|
|
59
61
|
function readSession(r) { return { publicKey: readKey(r), expiresAt: r.varint().toString(), asset: readAsset(r), allowance: r.varint().toString(), recipients: r.vec(rr => rr.string()) }; }
|
|
60
62
|
export function readAccountPolicy(r) {
|
|
61
63
|
const variant = Number(r.varint()), name = Object.keys(POLICY_VARIANT).find(n => POLICY_VARIANT[n] === variant);
|