@vultisig/core-mpc 1.16.1 → 1.17.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/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @vultisig/core-mpc
2
2
 
3
+ ## 1.17.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1696](https://github.com/vultisig/vultisig-sdk/pull/1696) [`37d7044`](https://github.com/vultisig/vultisig-sdk/commit/37d7044e33d475ddce93b91ff6295d55490052b4) Thanks [@Ehsan-saradar](https://github.com/Ehsan-saradar)! - Limit-order cancellation, end to end: a full-form memo asset, a cancel keysign payload builder, and cancel-aware review for co-signers.
8
+
9
+ The primitives shipped earlier could describe a cancellation but not send one, and a device joining the ceremony could not read one at all. These are the three pieces that close that.
10
+
11
+ `getThorchainCancelMemoAsset` emits the spelling a cancel requires — the same notation as the placement path, minus the abbreviation. That difference is the entire point: `ModifyLimitSwapMemo` is the one inbound memo type `processOneTxIn` does not route through `fuzzyAssetMatch`, so a placement's six-character contract suffix would address a bucket holding no order. `buildCancelLimitSwapMemo` already refused abbreviated assets, which meant there was previously no supported way to produce an input it would accept for a token leg. Both spellings now share one converter and one set of validation rules, so they cannot drift apart in anything but the abbreviation. `getThorchainMemoAssetChain` resolves a memo asset back to its home chain across every flavour, including the secured denoms that a `.`-split would fail to resolve at all.
12
+
13
+ `buildLimitSwapCancelKeysignPayload` turns that memo into a signable transaction, branching on where the order was funded: a THORChain source becomes a `MsgDeposit` carrying no value, and an L1 source a transfer to the live Asgard inbound with derived dust attached solely so Bifrost observes it. The signing asset is the funding chain's **gas** asset, never the order's own — a cancel moves no tokens, and a token here would build an ERC20 transfer that drops the memo entirely. Every gate fails closed: a retarget (`m=<` with a non-zero final field) is refused rather than signed as a cancellation, a memo that overflows the source chain's budget is refused rather than truncated into one matching nothing, and the destination is taken from a live inbound view rather than a cache.
14
+
15
+ The signing coin's chain is checked against the memo's, too. The two arrive as independent parameters, so a caller reaching for "the vault's ETH coin" while holding a BTC-sourced memo would otherwise get a payload that builds, signs and broadcasts cleanly — and is then refunded by THORChain's `From.IsChain(Source.Asset.GetChain())` check, leaving a successful-looking transaction that cancelled nothing. The funding chain is derived from the memo rather than cross-checked against a second parameter, so there is one authority for it. `getThorchainMemoAssetSourceChain` supplies that with `GetChain()` semantics rather than the asset's home chain: a secured or synth source is custodied on THORChain and must be sent from a THOR address even though it originates elsewhere.
16
+
17
+ The `EnableAdvSwapQueue` mimir is deliberately _not_ re-checked here, unlike at placement. That gate protects a new order from executing as an unprotected market swap, a risk a cancel does not carry; refusing to close an already-resting position because the queue stopped accepting new ones would strand it for the remainder of its TTL with no way out.
18
+
19
+ `getKeysignLimitSwapCancel` and `parseCancelLimitSwapMemo` give a joining device the order being closed, decoded from the memo. A cancel carries no swap payload on any branch, so a co-signer keying off one previously saw a dust transfer to an opaque address — worse than uninformative, since a trivial amount reads as harmless while the transaction closes a position. As with placement, the terms come from the memo because the memo is the instruction THORChain executes, so what a reviewer sees cannot disagree with what gets signed. A retarget is reported as not-a-cancellation rather than mislabelled, and the reproduced bucket key travels alongside so a reviewer holding the vault's open orders can tell whether the cancel is unambiguous.
20
+
21
+ `getThorchainCancelMemoAsset` emits its asset UPPER-CASED, unlike the coin's own contract id. Case is not semantic to THORNode — `common.ParseAsset` upper-cases whatever it is given, and the queue index key is built from an upper-cased asset — but it is semantic to this package's pool-id validation, which cancel eligibility routes through to size the memo against its source chain. In the contract's native lower case, every ERC20-funded order reads as an unroutable source chain and becomes uncancellable.
22
+
23
+ ### Patch Changes
24
+
25
+ - Updated dependencies [[`7d2a91d`](https://github.com/vultisig/vultisig-sdk/commit/7d2a91de80a297c6db6b2fe2e9db41ace609c822), [`37d7044`](https://github.com/vultisig/vultisig-sdk/commit/37d7044e33d475ddce93b91ff6295d55490052b4)]:
26
+ - @vultisig/core-chain@2.32.0
27
+
28
+ ## 1.16.2
29
+
30
+ ### Patch Changes
31
+
32
+ - [#1756](https://github.com/vultisig/vultisig-sdk/pull/1756) [`fbc5b44`](https://github.com/vultisig/vultisig-sdk/commit/fbc5b4445e102534eb434d7cabcd6fe8d633b391) Thanks [@Ehsan-saradar](https://github.com/Ehsan-saradar)! - Allow native swaps whose source is the protocol's own chain (RUNE on THORChain, CACAO on MayaChain) past the broadcast guard: those routes are MsgDeposits with no inbound vault and never appear in /inbound_addresses, so the inbound-existence and vault-address checks are skipped for them while quote-expiry and trading-halt checks still run.
33
+
34
+ - Updated dependencies [[`67667fe`](https://github.com/vultisig/vultisig-sdk/commit/67667fe61a8dd85d40c1b91978da5414987cab6c), [`fb601d5`](https://github.com/vultisig/vultisig-sdk/commit/fb601d5ad6f6e6a7089ca449ee24bc5c1d7b82f9)]:
35
+ - @vultisig/core-chain@2.31.2
36
+
3
37
  ## 1.16.1
4
38
 
5
39
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"assertNativeSwapReadyForBroadcast.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/swap/assertNativeSwapReadyForBroadcast.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAClD,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,oEAAoE,CAAA;AAC3E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,kDAAkD,CAAA;AAIzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAA;AAGxF,KAAK,6BAA6B,GAAG,CAAC,WAAW,EAAE,eAAe,KAAK,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAAA;AAEzG,MAAM,MAAM,6BAA6B,GAAG;IAC1C,KAAK,EAAE,KAAK,CAAA;IACZ,cAAc,EAAE,cAAc,CAAA;IAC9B,mBAAmB,CAAC,EAAE,6BAA6B,CAAA;IACnD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,iCAAiC,GACzC,gBAAgB,GAChB,eAAe,GACf,eAAe,GACf,mBAAmB,CAAA;AAEvB,qBAAa,6BAA8B,SAAQ,KAAK;IAEpD,QAAQ,CAAC,IAAI,EAAE,iCAAiC;gBAAvC,IAAI,EAAE,iCAAiC,EAChD,OAAO,EAAE,MAAM;CAKlB;AAUD;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC,GAAU,sDAKrD,6BAA6B,KAAG,OAAO,CAAC,IAAI,CAqG9C,CAAA"}
1
+ {"version":3,"file":"assertNativeSwapReadyForBroadcast.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/swap/assertNativeSwapReadyForBroadcast.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAClD,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,oEAAoE,CAAA;AAC3E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,kDAAkD,CAAA;AAIzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAA;AAGxF,KAAK,6BAA6B,GAAG,CAAC,WAAW,EAAE,eAAe,KAAK,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAAA;AAEzG,MAAM,MAAM,6BAA6B,GAAG;IAC1C,KAAK,EAAE,KAAK,CAAA;IACZ,cAAc,EAAE,cAAc,CAAA;IAC9B,mBAAmB,CAAC,EAAE,6BAA6B,CAAA;IACnD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,iCAAiC,GACzC,gBAAgB,GAChB,eAAe,GACf,eAAe,GACf,mBAAmB,CAAA;AAEvB,qBAAa,6BAA8B,SAAQ,KAAK;IAEpD,QAAQ,CAAC,IAAI,EAAE,iCAAiC;gBAAvC,IAAI,EAAE,iCAAiC,EAChD,OAAO,EAAE,MAAM;CAKlB;AAUD;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC,GAAU,sDAKrD,6BAA6B,KAAG,OAAO,CAAC,IAAI,CAmH9C,CAAA"}
@@ -58,8 +58,15 @@ export const assertNativeSwapReadyForBroadcast = async ({ chain, keysignPayload,
58
58
  throw new NativeSwapBroadcastGuardError('network_error', `Cannot fetch ${native.chain} inbound vaults for source chain ${sourceChainId}`);
59
59
  }
60
60
  const inboundByChainId = new Map(inboundAddresses.map(info => [info.chain.toUpperCase(), info]));
61
+ // sdk#1726: a swap whose SOURCE is the protocol's own chain (RUNE on THORChain, CACAO on
62
+ // MayaChain) is a MsgDeposit straight to the network - it has no inbound vault, and
63
+ // /inbound_addresses only lists external chains, so the lookup below is undefined by design.
64
+ // Skip the inbound-existence and vault-address checks for those routes (the same tolerance the
65
+ // halt loop below already applies); quote expiry and the halt checks still run. A RUNE source
66
+ // routed VIA Maya is NOT exempt: Maya's feed lists THOR as an external chain.
67
+ const sourceIsProtocolChain = chain === native.chain;
61
68
  const activeInbound = inboundByChainId.get(sourceChainId.toUpperCase());
62
- if (!activeInbound?.address) {
69
+ if (!sourceIsProtocolChain && !activeInbound?.address) {
63
70
  throw new NativeSwapBroadcastGuardError('network_error', `Cannot validate ${native.chain} inbound vault for source chain ${sourceChainId}`);
64
71
  }
65
72
  // sdk#1360: re-check the trading-halt flags at BROADCAST, not only at quote time
@@ -89,7 +96,12 @@ export const assertNativeSwapReadyForBroadcast = async ({ chain, keysignPayload,
89
96
  `refusing to broadcast into a halted chain`);
90
97
  }
91
98
  }
92
- if (activeInbound.address.toLowerCase() !== native.vaultAddress.toLowerCase()) {
99
+ // MsgDeposit payloads carry no vault address, so the staleness comparison is meaningless for
100
+ // protocol-chain sources even if the feed ever grew a THOR/MAYA entry.
101
+ if (sourceIsProtocolChain) {
102
+ return;
103
+ }
104
+ if (!activeInbound?.address || activeInbound.address.toLowerCase() !== native.vaultAddress.toLowerCase()) {
93
105
  throw new NativeSwapBroadcastGuardError('invalid_vault', `${native.chain} inbound vault address changed; refresh the swap quote before broadcasting`);
94
106
  }
95
107
  };
@@ -1 +1 @@
1
- {"version":3,"file":"assertNativeSwapReadyForBroadcast.js","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/swap/assertNativeSwapReadyForBroadcast.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"assertNativeSwapReadyForBroadcast.js","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/swap/assertNativeSwapReadyForBroadcast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import { AccountCoin } from '@vultisig/core-chain/coin/AccountCoin';
2
+ import { WalletCore } from '@trustwallet/wallet-core';
3
+ import { PublicKey } from '@trustwallet/wallet-core/dist/src/wallet-core';
4
+ import { KeysignLibType } from '../../mpcLib.js';
5
+ export type BuildLimitSwapCancelKeysignPayloadInput = {
6
+ /**
7
+ * The gas asset of the chain the order was FUNDED FROM — never the order's own
8
+ * asset. A cancel moves no tokens: it is a memo, carried by whatever the source
9
+ * chain charges to carry one. A BTC-funded order cancels with BTC; an
10
+ * ERC20-funded one cancels with ETH, not with the token.
11
+ */
12
+ signingCoin: AccountCoin;
13
+ /** The `m=<` memo from `buildCancelLimitSwapMemo`. */
14
+ memo: string;
15
+ vaultId: string;
16
+ localPartyId: string;
17
+ publicKey: PublicKey;
18
+ libType: KeysignLibType;
19
+ walletCore: WalletCore;
20
+ };
21
+ /**
22
+ * Build the `KeysignPayload` that cancels a resting THORChain limit order.
23
+ *
24
+ * Two branches, decided by where the order was funded:
25
+ *
26
+ * - **THORChain source** (RUNE, and THORChain-held assets) — `MsgDeposit` from
27
+ * the vault's own THOR address. No inbound vault and no real destination, so
28
+ * `toAddress` carries the signer's own address as a placeholder (the Cosmos
29
+ * signer keys off `isDeposit`, not `toAddress`) and no value is attached.
30
+ * - **L1 source** — a plain transfer to the chain's Asgard inbound vault with the
31
+ * memo attached. The amount is dust from `getLimitSwapCancelDust`, present
32
+ * solely so Bifrost observes the transaction; it is not a payment, and the
33
+ * router is deliberately not involved even for an ERC20-funded order, because
34
+ * `depositWithExpiry` exists to move tokens and a cancel moves none.
35
+ *
36
+ * Fund-safety gates, all fail-closed — a cancel that is accepted but matches
37
+ * nothing is indistinguishable from success, so every unknown refuses:
38
+ *
39
+ * - The memo must actually CANCEL. `m=<` with a non-zero final field re-prices a
40
+ * resting order instead of closing it, and must not be signed by a function
41
+ * whose callers believe they are cancelling.
42
+ * - The signing coin's chain must be the chain the memo says funded the order.
43
+ * These arrive as independent parameters, so a caller reaching for "the
44
+ * vault's ETH coin" while holding a BTC-sourced memo would otherwise get a
45
+ * payload that broadcasts cleanly and is then refunded by THORChain's
46
+ * `From.IsChain(Source.Asset.GetChain())` check — a successful-looking
47
+ * transaction that cancels nothing.
48
+ * - The memo must fit the source chain's per-transaction budget. A cancel cannot
49
+ * be shortened — its amounts define the bucket and its assets skip
50
+ * `fuzzyAssetMatch` — so an over-long one has to be refused here rather than
51
+ * silently truncated into a memo addressing nothing.
52
+ * - A THORChain-sourced cancel is blocked on THORChain's global trading pause,
53
+ * including when the inbound list is unverifiable, exactly as placement is.
54
+ * - An L1 cancel must resolve a live, non-halted, non-paused inbound, and takes
55
+ * its destination from that same live view rather than a cache. A cancel sent
56
+ * to a churned-away vault is as lost as a placement would be.
57
+ *
58
+ * Note what is NOT gated: the `EnableAdvSwapQueue` mimir, which placement does
59
+ * re-check at sign time. That gate protects a NEW `=<` order from executing as an
60
+ * unprotected market swap — a risk a cancel does not carry. Refusing to close an
61
+ * already-resting order because the queue stopped accepting new ones would strand
62
+ * a position for the remainder of its TTL with no way out, which is the worse
63
+ * failure of the two.
64
+ */
65
+ export declare const buildLimitSwapCancelKeysignPayload: ({ signingCoin, memo, vaultId, localPartyId, publicKey, libType, walletCore, }: BuildLimitSwapCancelKeysignPayloadInput) => Promise<import("../../types/vultisig/keysign/v1/keysign_message_pb.js").KeysignPayload>;
66
+ //# sourceMappingURL=buildLimitSwapCancelKeysignPayload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildLimitSwapCancelKeysignPayload.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/swap/buildLimitSwapCancelKeysignPayload.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AAWnE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAKzE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAI7C,MAAM,MAAM,uCAAuC,GAAG;IACpD;;;;;OAKG;IACH,WAAW,EAAE,WAAW,CAAA;IACxB,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,SAAS,CAAA;IACpB,OAAO,EAAE,cAAc,CAAA;IACvB,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,eAAO,MAAM,kCAAkC,GAAU,+EAQtD,uCAAuC,yFAyGzC,CAAA"}
@@ -0,0 +1,139 @@
1
+ import { Buffer } from 'buffer';
2
+ import { create } from '@bufbuild/protobuf';
3
+ import { Chain } from '@vultisig/core-chain/Chain';
4
+ import { isChainOfKind } from '@vultisig/core-chain/ChainKind';
5
+ import { getThorchainInboundAddress } from '@vultisig/core-chain/chains/cosmos/thor/getThorchainInboundAddress';
6
+ import { isFeeCoin } from '@vultisig/core-chain/coin/utils/isFeeCoin';
7
+ import { getLimitSwapCancelDust } from '@vultisig/core-chain/swap/native/limitSwapCancelDust';
8
+ import { doesCancelLimitSwapMemoFit, isCancelLimitSwapMemo, isModifyLimitSwapMemo, parseCancelLimitSwapMemo, } from '@vultisig/core-chain/swap/native/limitSwapCancelMemo';
9
+ import { findLimitSwapInbound, shouldBlockRuneDeposit } from '@vultisig/core-chain/swap/native/limitSwapInbound';
10
+ import { getThorchainMemoAssetSourceChain } from '@vultisig/core-chain/swap/native/thorchainMemoAsset';
11
+ import { getChainSpecific } from '../chainSpecific/index.js';
12
+ import { refineKeysignUtxo } from '../refine/utxo.js';
13
+ import { getKeysignUtxoInfo } from '../utxo/getKeysignUtxoInfo.js';
14
+ import { toCommCoin } from '../../types/utils/commCoin.js';
15
+ import { KeysignPayloadSchema } from '../../types/vultisig/keysign/v1/keysign_message_pb.js';
16
+ /**
17
+ * Build the `KeysignPayload` that cancels a resting THORChain limit order.
18
+ *
19
+ * Two branches, decided by where the order was funded:
20
+ *
21
+ * - **THORChain source** (RUNE, and THORChain-held assets) — `MsgDeposit` from
22
+ * the vault's own THOR address. No inbound vault and no real destination, so
23
+ * `toAddress` carries the signer's own address as a placeholder (the Cosmos
24
+ * signer keys off `isDeposit`, not `toAddress`) and no value is attached.
25
+ * - **L1 source** — a plain transfer to the chain's Asgard inbound vault with the
26
+ * memo attached. The amount is dust from `getLimitSwapCancelDust`, present
27
+ * solely so Bifrost observes the transaction; it is not a payment, and the
28
+ * router is deliberately not involved even for an ERC20-funded order, because
29
+ * `depositWithExpiry` exists to move tokens and a cancel moves none.
30
+ *
31
+ * Fund-safety gates, all fail-closed — a cancel that is accepted but matches
32
+ * nothing is indistinguishable from success, so every unknown refuses:
33
+ *
34
+ * - The memo must actually CANCEL. `m=<` with a non-zero final field re-prices a
35
+ * resting order instead of closing it, and must not be signed by a function
36
+ * whose callers believe they are cancelling.
37
+ * - The signing coin's chain must be the chain the memo says funded the order.
38
+ * These arrive as independent parameters, so a caller reaching for "the
39
+ * vault's ETH coin" while holding a BTC-sourced memo would otherwise get a
40
+ * payload that broadcasts cleanly and is then refunded by THORChain's
41
+ * `From.IsChain(Source.Asset.GetChain())` check — a successful-looking
42
+ * transaction that cancels nothing.
43
+ * - The memo must fit the source chain's per-transaction budget. A cancel cannot
44
+ * be shortened — its amounts define the bucket and its assets skip
45
+ * `fuzzyAssetMatch` — so an over-long one has to be refused here rather than
46
+ * silently truncated into a memo addressing nothing.
47
+ * - A THORChain-sourced cancel is blocked on THORChain's global trading pause,
48
+ * including when the inbound list is unverifiable, exactly as placement is.
49
+ * - An L1 cancel must resolve a live, non-halted, non-paused inbound, and takes
50
+ * its destination from that same live view rather than a cache. A cancel sent
51
+ * to a churned-away vault is as lost as a placement would be.
52
+ *
53
+ * Note what is NOT gated: the `EnableAdvSwapQueue` mimir, which placement does
54
+ * re-check at sign time. That gate protects a NEW `=<` order from executing as an
55
+ * unprotected market swap — a risk a cancel does not carry. Refusing to close an
56
+ * already-resting order because the queue stopped accepting new ones would strand
57
+ * a position for the remainder of its TTL with no way out, which is the worse
58
+ * failure of the two.
59
+ */
60
+ export const buildLimitSwapCancelKeysignPayload = async ({ signingCoin, memo, vaultId, localPartyId, publicKey, libType, walletCore, }) => {
61
+ if (!isCancelLimitSwapMemo(memo)) {
62
+ throw new Error(isModifyLimitSwapMemo(memo)
63
+ ? `buildLimitSwapCancelKeysignPayload: memo re-targets a limit order rather than cancelling it: ${JSON.stringify(memo)}`
64
+ : `buildLimitSwapCancelKeysignPayload: memo is not a THORChain limit-order cancel: ${JSON.stringify(memo)}`);
65
+ }
66
+ // Both branches spend gas and move nothing, so a token here means the caller
67
+ // passed the order's own asset rather than the funding chain's gas asset —
68
+ // which on an EVM chain would build an ERC20 transfer that drops the memo.
69
+ if (!isFeeCoin(signingCoin)) {
70
+ throw new Error(`buildLimitSwapCancelKeysignPayload: a cancel must be signed with ${signingCoin.chain}'s gas asset, got ${signingCoin.ticker}`);
71
+ }
72
+ // The coin and the memo arrive as independent parameters, and nothing above
73
+ // ties them together — so a caller that reaches for "the vault's ETH coin"
74
+ // while holding a BTC-sourced memo gets a payload that builds, signs and
75
+ // broadcasts cleanly. THORChain then refuses it at
76
+ // `MsgModifyLimitSwap.ValidateBasic`, which requires
77
+ // `From.IsChain(Source.Asset.GetChain())`, and refunds: a successful-looking
78
+ // transaction that cancels nothing, which is precisely the failure every other
79
+ // gate here exists to prevent.
80
+ //
81
+ // Derived from the memo rather than cross-checked against a second parameter,
82
+ // so there is one authority for which chain sends, and `GetChain()` semantics
83
+ // rather than the asset's home chain — a secured or synth source is custodied
84
+ // on THORChain and must be sent from a THOR address even though it originates
85
+ // elsewhere.
86
+ const sourceChain = getThorchainMemoAssetSourceChain(parseCancelLimitSwapMemo(memo).sourceAsset);
87
+ if (sourceChain === undefined) {
88
+ throw new Error(`buildLimitSwapCancelKeysignPayload: cannot resolve which chain must send this cancel from its memo: ${JSON.stringify(memo)}`);
89
+ }
90
+ if (sourceChain !== signingCoin.chain) {
91
+ throw new Error(`buildLimitSwapCancelKeysignPayload: this order was funded on ${sourceChain}, so its cancel must be sent from ${sourceChain}, not ${signingCoin.chain}`);
92
+ }
93
+ const isThorchainSource = sourceChain === Chain.THORChain;
94
+ if (!doesCancelLimitSwapMemoFit(memo, isChainOfKind(signingCoin.chain, 'utxo') ? 'utxo' : 'other')) {
95
+ throw new Error(`buildLimitSwapCancelKeysignPayload: the cancel memo does not fit ${signingCoin.chain}'s memo budget: ${JSON.stringify(memo)}`);
96
+ }
97
+ const hexPublicKey = Buffer.from(publicKey.data()).toString('hex');
98
+ const inbounds = await getThorchainInboundAddress();
99
+ const { toAddress, amount } = (() => {
100
+ if (isThorchainSource) {
101
+ if (shouldBlockRuneDeposit(inbounds)) {
102
+ throw new Error('THORChain has globally paused trading (or its inbound list is unverifiable); refusing to sign a limit-order cancel');
103
+ }
104
+ // A MsgDeposit carries no value for a cancel — the memo is the whole
105
+ // instruction — and the Cosmos signer routes on `isDeposit`, not on this
106
+ // address.
107
+ return { toAddress: signingCoin.address, amount: 0n };
108
+ }
109
+ const inbound = findLimitSwapInbound({ inbounds, chain: signingCoin.chain });
110
+ return {
111
+ toAddress: inbound.address,
112
+ amount: getLimitSwapCancelDust({ inbound, decimals: signingCoin.decimals }),
113
+ };
114
+ })();
115
+ let keysignPayload = create(KeysignPayloadSchema, {
116
+ coin: toCommCoin({ ...signingCoin, hexPublicKey }),
117
+ toAmount: amount.toString(),
118
+ vaultLocalPartyId: localPartyId,
119
+ vaultPublicKeyEcdsa: vaultId,
120
+ libType,
121
+ toAddress,
122
+ memo,
123
+ utxoInfo: await getKeysignUtxoInfo(signingCoin),
124
+ });
125
+ keysignPayload.blockchainSpecific = await getChainSpecific({
126
+ keysignPayload,
127
+ walletCore,
128
+ isDeposit: isThorchainSource,
129
+ });
130
+ if (isChainOfKind(signingCoin.chain, 'utxo')) {
131
+ keysignPayload = await refineKeysignUtxo({
132
+ keysignPayload,
133
+ walletCore,
134
+ publicKey,
135
+ });
136
+ }
137
+ return keysignPayload;
138
+ };
139
+ //# sourceMappingURL=buildLimitSwapCancelKeysignPayload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildLimitSwapCancelKeysignPayload.js","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/swap/buildLimitSwapCancelKeysignPayload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import { Chain } from '@vultisig/core-chain/Chain';
2
+ import { ParsedLimitSwapCancelMemo } from '@vultisig/core-chain/swap/native/limitSwapCancelMemo';
3
+ import { KeysignPayload } from '../../types/vultisig/keysign/v1/keysign_message_pb.js';
4
+ export type KeysignLimitSwapCancel = ParsedLimitSwapCancelMemo & {
5
+ /** Home chain of the sold asset, when its prefix is one this SDK can route. */
6
+ sourceChain?: Chain;
7
+ /** Home chain of the bought asset, under the same caveat. */
8
+ targetChain?: Chain;
9
+ /** The order's deposited amount, as a decimal string in display units. */
10
+ sourceAmountDecimal: string;
11
+ /** The order's original minimum-received, as a decimal string in display units. */
12
+ tradeTargetDecimal: string;
13
+ /**
14
+ * The advanced-swap-queue bucket this cancel will address, reproduced from the
15
+ * memo. Two orders sharing it are not independently cancellable, so a reviewer
16
+ * holding the vault's open orders can tell whether this cancel is unambiguous.
17
+ */
18
+ bucketKey: string;
19
+ };
20
+ /**
21
+ * Decode the limit order a keysign payload is about to CANCEL, for review.
22
+ *
23
+ * Returns `undefined` for any payload that is not a limit-order cancellation, so
24
+ * a caller can branch on it directly.
25
+ *
26
+ * **This is how a *joining* device reviews a cancellation.** A cancel carries no
27
+ * swap payload on any branch — it is a `MsgDeposit` or a dust transfer to an
28
+ * inbound vault — so a co-signer keying off the swap payload alone sees a send of
29
+ * a trivial amount to an opaque address with an opaque memo, with nothing saying
30
+ * an order is being closed. Worse than uninformative: the visible amount is dust,
31
+ * which reads as harmless while the transaction closes a position.
32
+ *
33
+ * As with placement, the terms come from `keysignPayload.memo` because the memo
34
+ * IS the instruction THORChain executes, so what a reviewer sees cannot disagree
35
+ * with what gets signed — unlike a display field supplied alongside it, which a
36
+ * co-signer has no way to verify.
37
+ *
38
+ * A *retarget* is deliberately not reported here. `m=<` with a non-zero final
39
+ * field re-prices an order rather than closing it, and a reviewer told "this
40
+ * cancels your order" would be approving something else entirely; the parser
41
+ * rejects it and this returns `undefined`.
42
+ */
43
+ export declare const getKeysignLimitSwapCancel: ({ memo, }: Pick<KeysignPayload, "memo">) => KeysignLimitSwapCancel | undefined;
44
+ //# sourceMappingURL=getKeysignLimitSwapCancel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getKeysignLimitSwapCancel.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/swap/getKeysignLimitSwapCancel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAGlD,OAAO,EAGL,yBAAyB,EAC1B,MAAM,sDAAsD,CAAA;AAI7D,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAA;AAKnF,MAAM,MAAM,sBAAsB,GAAG,yBAAyB,GAAG;IAC/D,+EAA+E;IAC/E,WAAW,CAAC,EAAE,KAAK,CAAA;IACnB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,KAAK,CAAA;IACnB,0EAA0E;IAC1E,mBAAmB,EAAE,MAAM,CAAA;IAC3B,mFAAmF;IACnF,kBAAkB,EAAE,MAAM,CAAA;IAC1B;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,yBAAyB,GAAI,WAEvC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,KAAG,sBAAsB,GAAG,SAoB1D,CAAA"}
@@ -0,0 +1,51 @@
1
+ import { fromChainAmountDisplay } from '@vultisig/core-chain/amount/fromChainAmountExact';
2
+ import { Chain } from '@vultisig/core-chain/Chain';
3
+ import { chainFeeCoin } from '@vultisig/core-chain/coin/chainFeeCoin';
4
+ import { getThorchainLimitOrderBucketKey } from '@vultisig/core-chain/swap/native/limitSwapCancelBucket';
5
+ import { isModifyLimitSwapMemo, parseCancelLimitSwapMemo, } from '@vultisig/core-chain/swap/native/limitSwapCancelMemo';
6
+ import { getThorchainMemoAssetChain } from '@vultisig/core-chain/swap/native/thorchainMemoAsset';
7
+ import { attempt } from '@vultisig/lib-utils/attempt';
8
+ /** THORChain's fixed point, which both amounts in a cancel memo are expressed in. */
9
+ const thorchainDecimals = chainFeeCoin[Chain.THORChain].decimals;
10
+ /**
11
+ * Decode the limit order a keysign payload is about to CANCEL, for review.
12
+ *
13
+ * Returns `undefined` for any payload that is not a limit-order cancellation, so
14
+ * a caller can branch on it directly.
15
+ *
16
+ * **This is how a *joining* device reviews a cancellation.** A cancel carries no
17
+ * swap payload on any branch — it is a `MsgDeposit` or a dust transfer to an
18
+ * inbound vault — so a co-signer keying off the swap payload alone sees a send of
19
+ * a trivial amount to an opaque address with an opaque memo, with nothing saying
20
+ * an order is being closed. Worse than uninformative: the visible amount is dust,
21
+ * which reads as harmless while the transaction closes a position.
22
+ *
23
+ * As with placement, the terms come from `keysignPayload.memo` because the memo
24
+ * IS the instruction THORChain executes, so what a reviewer sees cannot disagree
25
+ * with what gets signed — unlike a display field supplied alongside it, which a
26
+ * co-signer has no way to verify.
27
+ *
28
+ * A *retarget* is deliberately not reported here. `m=<` with a non-zero final
29
+ * field re-prices an order rather than closing it, and a reviewer told "this
30
+ * cancels your order" would be approving something else entirely; the parser
31
+ * rejects it and this returns `undefined`.
32
+ */
33
+ export const getKeysignLimitSwapCancel = ({ memo, }) => {
34
+ if (!isModifyLimitSwapMemo(memo) || !memo) {
35
+ return undefined;
36
+ }
37
+ const parsed = attempt(() => parseCancelLimitSwapMemo(memo));
38
+ if ('error' in parsed) {
39
+ return undefined;
40
+ }
41
+ const { data: cancel } = parsed;
42
+ return {
43
+ ...cancel,
44
+ sourceChain: getThorchainMemoAssetChain(cancel.sourceAsset),
45
+ targetChain: getThorchainMemoAssetChain(cancel.targetAsset),
46
+ sourceAmountDecimal: fromChainAmountDisplay(cancel.sourceAmount, thorchainDecimals),
47
+ tradeTargetDecimal: fromChainAmountDisplay(cancel.tradeTarget, thorchainDecimals),
48
+ bucketKey: getThorchainLimitOrderBucketKey(cancel),
49
+ };
50
+ };
51
+ //# sourceMappingURL=getKeysignLimitSwapCancel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getKeysignLimitSwapCancel.js","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/swap/getKeysignLimitSwapCancel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kDAAkD,CAAA;AACzF,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AACrE,OAAO,EAAE,+BAA+B,EAAE,MAAM,wDAAwD,CAAA;AACxG,OAAO,EACL,qBAAqB,EACrB,wBAAwB,GAEzB,MAAM,sDAAsD,CAAA;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,qDAAqD,CAAA;AAChG,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAIrD,qFAAqF;AACrF,MAAM,iBAAiB,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAA;AAmBhE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,EACxC,IAAI,GACyB,EAAsC,EAAE;IACrE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1C,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAA;IAC5D,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;QACtB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAA;IAE/B,OAAO;QACL,GAAG,MAAM;QACT,WAAW,EAAE,0BAA0B,CAAC,MAAM,CAAC,WAAW,CAAC;QAC3D,WAAW,EAAE,0BAA0B,CAAC,MAAM,CAAC,WAAW,CAAC;QAC3D,mBAAmB,EAAE,sBAAsB,CAAC,MAAM,CAAC,YAAY,EAAE,iBAAiB,CAAC;QACnF,kBAAkB,EAAE,sBAAsB,CAAC,MAAM,CAAC,WAAW,EAAE,iBAAiB,CAAC;QACjF,SAAS,EAAE,+BAA+B,CAAC,MAAM,CAAC;KACnD,CAAA;AACH,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vultisig/core-mpc",
3
- "version": "1.16.1",
3
+ "version": "1.17.0",
4
4
  "description": "MPC, keysign, and vault types shared across Vultisig clients",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -591,6 +591,11 @@
591
591
  "import": "./dist/keysign/swap/build.js",
592
592
  "default": "./dist/keysign/swap/build.js"
593
593
  },
594
+ "./keysign/swap/buildLimitSwapCancelKeysignPayload": {
595
+ "types": "./dist/keysign/swap/buildLimitSwapCancelKeysignPayload.d.ts",
596
+ "import": "./dist/keysign/swap/buildLimitSwapCancelKeysignPayload.js",
597
+ "default": "./dist/keysign/swap/buildLimitSwapCancelKeysignPayload.js"
598
+ },
594
599
  "./keysign/swap/buildLimitSwapKeysignPayload": {
595
600
  "types": "./dist/keysign/swap/buildLimitSwapKeysignPayload.d.ts",
596
601
  "import": "./dist/keysign/swap/buildLimitSwapKeysignPayload.js",
@@ -601,6 +606,11 @@
601
606
  "import": "./dist/keysign/swap/cowswap/buildCowSwapApprovalSigningInput.js",
602
607
  "default": "./dist/keysign/swap/cowswap/buildCowSwapApprovalSigningInput.js"
603
608
  },
609
+ "./keysign/swap/getKeysignLimitSwapCancel": {
610
+ "types": "./dist/keysign/swap/getKeysignLimitSwapCancel.d.ts",
611
+ "import": "./dist/keysign/swap/getKeysignLimitSwapCancel.js",
612
+ "default": "./dist/keysign/swap/getKeysignLimitSwapCancel.js"
613
+ },
604
614
  "./keysign/swap/getKeysignLimitSwapOrder": {
605
615
  "types": "./dist/keysign/swap/getKeysignLimitSwapOrder.d.ts",
606
616
  "import": "./dist/keysign/swap/getKeysignLimitSwapOrder.js",
@@ -1079,7 +1089,7 @@
1079
1089
  "@noble/hashes": "^1.8.0",
1080
1090
  "@solana/web3.js": "^1.98.4",
1081
1091
  "@trustwallet/wallet-core": "^4.7.0",
1082
- "@vultisig/core-chain": "2.31.1",
1092
+ "@vultisig/core-chain": "2.32.0",
1083
1093
  "@vultisig/core-config": "0.9.1",
1084
1094
  "@vultisig/lib-dkls": "0.9.0",
1085
1095
  "@vultisig/lib-mldsa": "0.9.0",