@vultisig/core-mpc 2.1.1 → 3.0.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/CHANGELOG.md +70 -0
- package/dist/keysign/chainSpecific/KeysignChainSpecific.d.ts +0 -1
- package/dist/keysign/chainSpecific/KeysignChainSpecific.d.ts.map +1 -1
- package/dist/keysign/chainSpecific/KeysignChainSpecific.js +0 -1
- package/dist/keysign/chainSpecific/KeysignChainSpecific.js.map +1 -1
- package/dist/keysign/chainSpecific/resolver.d.ts +10 -0
- package/dist/keysign/chainSpecific/resolver.d.ts.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/ripple.d.ts +11 -0
- package/dist/keysign/chainSpecific/resolvers/ripple.d.ts.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/ripple.js +110 -5
- package/dist/keysign/chainSpecific/resolvers/ripple.js.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/ton/index.d.ts.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/ton/index.js +79 -29
- package/dist/keysign/chainSpecific/resolvers/ton/index.js.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/tron/index.d.ts +18 -0
- package/dist/keysign/chainSpecific/resolvers/tron/index.d.ts.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/tron/index.js +66 -7
- package/dist/keysign/chainSpecific/resolvers/tron/index.js.map +1 -1
- package/dist/keysign/error.d.ts +1 -1
- package/dist/keysign/error.d.ts.map +1 -1
- package/dist/keysign/error.js.map +1 -1
- package/dist/keysign/send/build.d.ts +2 -1
- package/dist/keysign/send/build.d.ts.map +1 -1
- package/dist/keysign/send/build.js +55 -0
- package/dist/keysign/send/build.js.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ripple.d.ts.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ripple.js +55 -17
- package/dist/keysign/signingInputs/resolvers/ripple.js.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ton/index.d.ts.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ton/index.js +5 -1
- package/dist/keysign/signingInputs/resolvers/ton/index.js.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ton/jetton.d.ts.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ton/jetton.js +11 -3
- package/dist/keysign/signingInputs/resolvers/ton/jetton.js.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ton/native.d.ts +0 -2
- package/dist/keysign/signingInputs/resolvers/ton/native.d.ts.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ton/native.js +4 -17
- package/dist/keysign/signingInputs/resolvers/ton/native.js.map +1 -1
- package/dist/keysign/utils/isRippleTrustSet.d.ts +8 -23
- package/dist/keysign/utils/isRippleTrustSet.d.ts.map +1 -1
- package/dist/keysign/utils/isRippleTrustSet.js +15 -24
- package/dist/keysign/utils/isRippleTrustSet.js.map +1 -1
- package/dist/types/vultisig/keysign/v1/blockchain_specific_pb.d.ts +9 -1
- package/dist/types/vultisig/keysign/v1/blockchain_specific_pb.d.ts.map +1 -1
- package/dist/types/vultisig/keysign/v1/blockchain_specific_pb.js +9 -1
- package/dist/types/vultisig/keysign/v1/blockchain_specific_pb.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# @vultisig/core-mpc
|
|
2
2
|
|
|
3
|
+
## 3.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#2323](https://github.com/vultisig/vultisig-sdk/pull/2323) [`8a50970`](https://github.com/vultisig/vultisig-sdk/commit/8a50970438de64cdbeb281cf73925026e3ce3cf7) Thanks [@Ehsan-saradar](https://github.com/Ehsan-saradar)! - Refuse XRPL issued-currency Payments the ledger would reject — a destination holding no trust line for the token, and an issuer that charges a transfer fee the payload cannot yet cover with a SendMax — instead of burning the fee on-chain. Accept the lowercase standard currency codes XRPL permits, report bad amounts and unusable destinations as domain errors, and pin both encoders against a shared issued-currency signing vector.
|
|
8
|
+
|
|
9
|
+
- [#2310](https://github.com/vultisig/vultisig-sdk/pull/2310) [`af6c643`](https://github.com/vultisig/vultisig-sdk/commit/af6c643e9afa39cb0b4432a01cec40e4de4d8ecc) Thanks [@Ehsan-saradar](https://github.com/Ehsan-saradar)! - fix(ton): let a dApp deadline tighten the signed expiry
|
|
10
|
+
|
|
11
|
+
`getTonChainSpecific` always signed `expireAt = now + 600`, so the `valid_until` a TonConnect `sendTransaction` carries never reached the wallet message: a request with a 60-second window was signed with a ten-minute one, and a broadcast landing after the dApp's window could execute on chain while the dApp already treated it as expired and retried.
|
|
12
|
+
|
|
13
|
+
`GetChainSpecificInput` now takes an optional `validUntil` (unix seconds) for `tonSpecific`. The signed `expireAt` is `min(now + 600, validUntil)` — the wallet's own window remains the ceiling — and a deadline already in the past fails the build instead of signing a transaction the network would reject. Callers that pass nothing keep the previous behaviour; co-signers read `expireAt` from the payload, so only what the initiator writes changes.
|
|
14
|
+
|
|
15
|
+
The expiry is computed last, after the seqno, bounceability and jetton-metadata lookups: each is a network round trip, so a deadline still ahead when the build starts can be behind by the time it finishes, and the wallet's own ten-minute window now starts when the payload is finished rather than being partly spent on those lookups.
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [[`8a50970`](https://github.com/vultisig/vultisig-sdk/commit/8a50970438de64cdbeb281cf73925026e3ce3cf7), [`af6c643`](https://github.com/vultisig/vultisig-sdk/commit/af6c643e9afa39cb0b4432a01cec40e4de4d8ecc), [`20de22f`](https://github.com/vultisig/vultisig-sdk/commit/20de22f49c244ffc065011291754f89ef0d6e61a), [`34f0faa`](https://github.com/vultisig/vultisig-sdk/commit/34f0faa7208ad594b8d18a3a2806c0f7867f2c85)]:
|
|
18
|
+
- @vultisig/core-chain@5.1.0
|
|
19
|
+
|
|
20
|
+
## 3.0.0
|
|
21
|
+
|
|
22
|
+
### Major Changes
|
|
23
|
+
|
|
24
|
+
- [#2237](https://github.com/vultisig/vultisig-sdk/pull/2237) [`7d4c116`](https://github.com/vultisig/vultisig-sdk/commit/7d4c116cc7a940e96abf075790c4a387edd03987) Thanks [@Ehsan-saradar](https://github.com/Ehsan-saradar)! - Remove Kujira (KUJI) chain support. Kujira wound down in 2025 and every RPC/LCD endpoint the SDK shipped for it is now dead (the polkachu hosts no longer resolve; publicnode 404s), so balances, sends, swaps, staking and governance on Kujira cannot function.
|
|
25
|
+
|
|
26
|
+
`Chain.Kujira` / `CosmosChain.Kujira` are removed from the chain union, along with the Kujira entries in the chain registry, cosmos RPC/LCD/fee/gas/memo tables, SwapKit + Skip + native-swap routing, the Kujira token list, IBC chain-id mapping, governance config and address derivation.
|
|
27
|
+
|
|
28
|
+
The IBC tables in `tools/prep/ibcTransfer.ts` are keyed by raw chain-ID rather than the `Chain` enum, so they are cleared explicitly: `kaiyo-1` is dropped from `IBC_CHAIN_REVISION` and the `osmosis-1/channel-259` route from `IBC_CHANNEL_DEST`. `supportedIbcDestinationsFrom('osmosis-1')` no longer advertises `kaiyo-1`, and `resolveSourceChannelByDestChain('osmosis-1', 'kaiyo-1')` returns `null`.
|
|
29
|
+
|
|
30
|
+
`COSMOS_CHAIN_ID_HRP` keeps its `kaiyo-1` → `kujira` entry: it is a pure bech32-prefix lookup that makes nothing routable, and it is still needed to decode historic `kujira1…` addresses.
|
|
31
|
+
|
|
32
|
+
The `chains/cosmos/thor/kujira-merge` module is intentionally **kept**: it describes the six Kujira-origin tokens (KUJI, rKUJI, FUZN, NSTK, WINK, LVN) that migrated onto THORChain as `thor.*` secured assets, plus their IBC representations on Cosmos Hub and Osmosis. Those assets are unaffected and keep resolving.
|
|
33
|
+
|
|
34
|
+
Consumers holding a persisted `Chain.Kujira` value must drop it — the symbol no longer type-checks.
|
|
35
|
+
|
|
36
|
+
- [#2298](https://github.com/vultisig/vultisig-sdk/pull/2298) [`1716a79`](https://github.com/vultisig/vultisig-sdk/commit/1716a7946bf617ff16f8bb15f33b279efbb4a87d) Thanks [@Ehsan-saradar](https://github.com/Ehsan-saradar)! - fix(ton): one correct comment validator, run before the user signs
|
|
37
|
+
|
|
38
|
+
TON comment length was checked against a fixed 123 bytes wherever it was checked at all. That number is right for a native transfer, where the comment is the message body's own cell, and wrong for a jetton transfer, where the comment rides inline in the transfer body's `forward_payload` and shares one 1023-bit cell with the opcode, query id, amount, both addresses and the forward amount. The real jetton cap is roughly 34–39 bytes and SHRINKS as the amount grows, because `VarUInteger 16` widens a byte at a time. Anything above it reached WalletCore, which refuses to pack the cell and fails the keysign with a bare "Internal error" — after the user had reviewed and approved the transaction. Memos are load-bearing on TON; an exchange deposit without the right one loses the funds.
|
|
39
|
+
|
|
40
|
+
New `@vultisig/core-chain/chains/ton/comment` owns the rule for both shapes: `tonNativeCommentMaxBytes`, `getTonJettonCommentMaxBytes({ amount, isActiveDestination })`, `getTonCommentMaxBytes` for a send form that wants to count down against the real limit, and `validateTonComment`. The amount-dependent widths are measured by encoding them, not predicted, and a test drives real WalletCore at each cap and one byte past it to prove the two agree.
|
|
41
|
+
|
|
42
|
+
`buildSendKeysignPayload` now validates the memo at the end of the build, where the final signed amount and `isActiveDestination` are both known, and raises a non-retryable `BuildKeysignPayloadError('ton-memo-too-long')`. That moves the failure from keysign to the point where the payload is assembled — the verify screen — for every consumer, with no client-side change. The signing-input resolvers still validate, so a payload built by another device or an older client cannot get an unpackable comment signed here either.
|
|
43
|
+
|
|
44
|
+
**Breaking:** `validateTonComment` is no longer exported from `@vultisig/core-mpc/keysign/signingInputs/resolvers/ton/native`, and takes `{ memo, jetton? }` instead of a bare string. Import it from `@vultisig/core-chain/chains/ton/comment`. `validateTonMemo` in the SDK's TON surface keeps its signature and gains an optional second argument for jetton context.
|
|
45
|
+
|
|
46
|
+
### Minor Changes
|
|
47
|
+
|
|
48
|
+
- [#2316](https://github.com/vultisig/vultisig-sdk/pull/2316) [`b19c5d5`](https://github.com/vultisig/vultisig-sdk/commit/b19c5d56f4d00d92493f8da74ff80d92b1d87c68) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Add exact XRP Ledger issued-currency Payments and authoritative delivered-amount receipts for XRP, issued currencies, and MPTs while preserving native XRP and explicit TrustSet behavior.
|
|
49
|
+
|
|
50
|
+
### Patch Changes
|
|
51
|
+
|
|
52
|
+
- [#2282](https://github.com/vultisig/vultisig-sdk/pull/2282) [`a711b6c`](https://github.com/vultisig/vultisig-sdk/commit/a711b6ca8a8a7ae39d0efbb1c919b23b6538a1b8) Thanks [@Ehsan-saradar](https://github.com/Ehsan-saradar)! - fix(ton): derive each dApp message's bounce flag from its own destination
|
|
53
|
+
|
|
54
|
+
A dApp `signTon` batch stamped every message with the single wallet-level `TonSpecific.bounceable`, which the chain-specific resolver computes from the first message's destination alone. The bounce bit a message declares lives in its own address tag — `EQ…`/`kQ…` bounceable, `UQ…`/`0Q…` not, a raw `workchain:hex` address none — so a batch with mixed destinations, or a first destination that is not yet deployed, signed the wrong bit on some of its messages, and a co-signer deriving the flag per address computed a different hash for the same payload.
|
|
55
|
+
|
|
56
|
+
Each dApp message now takes the flag from its own destination (`getTonMessageBounceable` in `@vultisig/core-chain/chains/ton/messageBounce`); a raw `workchain:hex` address carries no tag, so it defaults to bounceable — an already-deployed contract must refund a rejection — unless the message carries `stateInit`, the deployment case whose destination has no code yet to bounce from. Every raw spelling WalletCore signs counts as the same account here: leading zeros, an explicit sign and a `0x`-prefixed hash all name one address and compile to one pre-image, so `00:<hash>` cannot be signed non-bounceable while `0:<hash>` is signed bounceable. App-initiated single sends are unchanged and keep the wallet-level flag and the nominator-pool override.
|
|
57
|
+
|
|
58
|
+
The bounce bit is part of the signed body, so TON signing hashes move for dApp batches whose destinations do not all share the first message's flag. Co-signers must apply the same per-message rule.
|
|
59
|
+
|
|
60
|
+
- [#2255](https://github.com/vultisig/vultisig-sdk/pull/2255) [`ef6a8bb`](https://github.com/vultisig/vultisig-sdk/commit/ef6a8bb0007c6576179e5a8cb10aa47820075b57) Thanks [@Ehsan-saradar](https://github.com/Ehsan-saradar)! - fix(ton): send swap deposits bounceable so a rejected deposit is refunded
|
|
61
|
+
|
|
62
|
+
TON transfers were marked bounceable only when the destination string started with `E`. Swap providers hand back deposit addresses in the `UQ…` (non-bounceable) form, so every TON swap deposit went out non-bounceable — and a router or escrow contract that rejects a message (expired quote, paused pool, closed route) _absorbs_ a non-bounceable transfer instead of returning it. The funds were gone.
|
|
63
|
+
|
|
64
|
+
Swap deposits are now always sent bounceable. The prefix check is replaced by a real read of the address's bounce tag, so raw `0:hex` destinations — which declare no bounceability at all and which the prefix check silently treated as non-bounceable — default to bounceable, the safe side for anything that might be a contract. Sends to an undeployed account stay non-bounceable, since such an account cannot accept a bounceable message, and an explicit `UQ…` destination is still honoured.
|
|
65
|
+
|
|
66
|
+
Adds `getTonAddressBounceability` to `@vultisig/core-chain/chains/ton/address`.
|
|
67
|
+
|
|
68
|
+
- [#2318](https://github.com/vultisig/vultisig-sdk/pull/2318) [`26a83ed`](https://github.com/vultisig/vultisig-sdk/commit/26a83ed417c9543f9c92d28cbb1bd35f0f914817) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Fix TRON transaction lifecycle safety across fee preparation, status polling, and broadcast. Native TRX bandwidth estimates now measure the WalletCore-serialized signed transaction including memo bytes, default transaction times use the fetched block timestamp, expired raw transactions terminate polling, and successful broadcasts must return the deterministic local transaction hash.
|
|
69
|
+
|
|
70
|
+
- Updated dependencies [[`1b3fb49`](https://github.com/vultisig/vultisig-sdk/commit/1b3fb498ad3f78b84b92b9f09b41fe8956fc5e9a), [`7d4c116`](https://github.com/vultisig/vultisig-sdk/commit/7d4c116cc7a940e96abf075790c4a387edd03987), [`7b65284`](https://github.com/vultisig/vultisig-sdk/commit/7b65284f7fe73f538283a201a416efdbbda0830c), [`1716a79`](https://github.com/vultisig/vultisig-sdk/commit/1716a7946bf617ff16f8bb15f33b279efbb4a87d), [`a711b6c`](https://github.com/vultisig/vultisig-sdk/commit/a711b6ca8a8a7ae39d0efbb1c919b23b6538a1b8), [`ef6a8bb`](https://github.com/vultisig/vultisig-sdk/commit/ef6a8bb0007c6576179e5a8cb10aa47820075b57), [`26a83ed`](https://github.com/vultisig/vultisig-sdk/commit/26a83ed417c9543f9c92d28cbb1bd35f0f914817), [`b19c5d5`](https://github.com/vultisig/vultisig-sdk/commit/b19c5d56f4d00d92493f8da74ff80d92b1d87c68)]:
|
|
71
|
+
- @vultisig/core-chain@5.0.0
|
|
72
|
+
|
|
3
73
|
## 2.1.1
|
|
4
74
|
|
|
5
75
|
### Patch Changes
|
|
@@ -28,7 +28,6 @@ export declare const chainSpecificRecord: {
|
|
|
28
28
|
readonly Cosmos: "cosmosSpecific";
|
|
29
29
|
readonly Osmosis: "cosmosSpecific";
|
|
30
30
|
readonly Dydx: "cosmosSpecific";
|
|
31
|
-
readonly Kujira: "cosmosSpecific";
|
|
32
31
|
readonly Terra: "cosmosSpecific";
|
|
33
32
|
readonly TerraClassic: "cosmosSpecific";
|
|
34
33
|
readonly Noble: "cosmosSpecific";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeysignChainSpecific.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/chainSpecific/KeysignChainSpecific.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,iEAAiE,CAAA;AAGhG,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,oBAAoB,CAAC,EAAE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC,CAAA;AAExH,MAAM,MAAM,uBAAuB,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;AAElE,eAAO,MAAM,mBAAmB
|
|
1
|
+
{"version":3,"file":"KeysignChainSpecific.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/chainSpecific/KeysignChainSpecific.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,iEAAiE,CAAA;AAGhG,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,oBAAoB,CAAC,EAAE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC,CAAA;AAExH,MAAM,MAAM,uBAAuB,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;AAElE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoD2B,CAAA;AAE3D,eAAO,MAAM,0BAA0B,GAAI,CAAC,SAAS,uBAAuB,EAC1E,oBAAoB,cAAc,CAAC,oBAAoB,CAAC,EACxD,cAAc,CAAC,KACd,OAAO,CAAC,oBAAoB,EAAE;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC,CAAC,OAAO,CAMpD,CAAA"}
|
|
@@ -24,7 +24,6 @@ export const chainSpecificRecord = {
|
|
|
24
24
|
[Chain.Cosmos]: 'cosmosSpecific',
|
|
25
25
|
[Chain.Osmosis]: 'cosmosSpecific',
|
|
26
26
|
[Chain.Dydx]: 'cosmosSpecific',
|
|
27
|
-
[Chain.Kujira]: 'cosmosSpecific',
|
|
28
27
|
[Chain.Terra]: 'cosmosSpecific',
|
|
29
28
|
[Chain.TerraClassic]: 'cosmosSpecific',
|
|
30
29
|
[Chain.Noble]: 'cosmosSpecific',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeysignChainSpecific.js","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/chainSpecific/KeysignChainSpecific.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAElD,OAAO,EAAE,0BAA0B,EAAE,MAAM,gDAAgD,CAAA;AAM3F,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,kBAAkB;IACpC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,kBAAkB;IACrC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,kBAAkB;IAChC,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,kBAAkB;IACvC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,kBAAkB;IAC/B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,kBAAkB;IACjC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,kBAAkB;IACpC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,kBAAkB;IACpC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,kBAAkB;IACnC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,kBAAkB;IAClC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,kBAAkB;IAClC,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,kBAAkB;IACvC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,kBAAkB;IAC/B,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,kBAAkB;IAErC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,cAAc;IAC/B,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,cAAc;IACnC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,cAAc;IAChC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,cAAc;IAChC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,cAAc;IAC5B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,cAAc;IAE7B,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,gBAAgB;IAChC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,gBAAgB;IACjC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,gBAAgB;IAC9B,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"KeysignChainSpecific.js","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/chainSpecific/KeysignChainSpecific.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAElD,OAAO,EAAE,0BAA0B,EAAE,MAAM,gDAAgD,CAAA;AAM3F,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,kBAAkB;IACpC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,kBAAkB;IACrC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,kBAAkB;IAChC,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,kBAAkB;IACvC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,kBAAkB;IAC/B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,kBAAkB;IACjC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,kBAAkB;IACpC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,kBAAkB;IACpC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,kBAAkB;IACnC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,kBAAkB;IAClC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,kBAAkB;IAClC,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,kBAAkB;IACvC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,kBAAkB;IAC/B,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,kBAAkB;IAErC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,cAAc;IAC/B,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,cAAc;IACnC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,cAAc;IAChC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,cAAc;IAChC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,cAAc;IAC5B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,cAAc;IAE7B,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,gBAAgB;IAChC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,gBAAgB;IACjC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,gBAAgB;IAC9B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,gBAAgB;IAC/B,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,gBAAgB;IACtC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,gBAAgB;IAC/B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,gBAAgB;IAE/B,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,mBAAmB;IAEtC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,cAAc;IAEjC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,gBAAgB;IAE7B,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,gBAAgB;IAEhC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,kBAAkB;IAEpC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,kBAAkB;IAErC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,aAAa;IAE1B,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,gBAAgB;IAEhC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,cAAc;IAE5B,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,SAAS;IAE1B,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,gBAAgB;CAC2B,CAAA;AAE3D,MAAM,CAAC,MAAM,0BAA0B,GAAG,CACxC,kBAAwD,EACxD,YAAe,EACsC,EAAE;IACvD,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAChD,CAAC;IAED,OAAO,0BAA0B,CAAC,kBAAkB,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAQ,CAAA;AAC7F,CAAC,CAAA"}
|
|
@@ -40,6 +40,16 @@ export type GetChainSpecificInput<C extends KeysignChainSpecificKey = KeysignCha
|
|
|
40
40
|
refBlockBytesHex?: string;
|
|
41
41
|
refBlockHashHex?: string;
|
|
42
42
|
thirdPartyGasLimitEstimation?: bigint;
|
|
43
|
+
} : C extends 'rippleSpecific' ? {
|
|
44
|
+
/** Explicit send intent overrides the legacy issuer-address TrustSet inference. */
|
|
45
|
+
transactionType?: TransactionType.RIPPLE_PAYMENT | TransactionType.RIPPLE_TRUST_SET;
|
|
46
|
+
} : C extends 'tonSpecific' ? {
|
|
47
|
+
/**
|
|
48
|
+
* Deadline (unix seconds) a dApp attached to the request — a TonConnect
|
|
49
|
+
* `sendTransaction` `valid_until`. Caps the wallet's own expiry; a deadline
|
|
50
|
+
* already in the past fails the build instead of signing a dead transaction.
|
|
51
|
+
*/
|
|
52
|
+
validUntil?: number;
|
|
43
53
|
} : {});
|
|
44
54
|
export type GetChainSpecificResolver<C extends KeysignChainSpecificKey = KeysignChainSpecificKey> = Resolver<GetChainSpecificInput<C>, Promise<ValueForCase<C>>>;
|
|
45
55
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/chainSpecific/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qEAAqE,CAAA;AAC1G,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAEpC,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAA;AACnF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAEtF,KAAK,YAAY,CAAC,CAAC,SAAS,uBAAuB,IAAI,OAAO,CAAC,oBAAoB,EAAE;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC,CAAC,OAAO,CAAC,CAAA;AAE1G,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,uBAAuB,GAAG,uBAAuB,IAAI;IAC/F,cAAc,EAAE,cAAc,CAAA;IAC9B,UAAU,EAAE,UAAU,CAAA;IACtB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,GAAG,CAAC,CAAC,SAAS,kBAAkB,GAC7B;IACE,WAAW,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,CAAA;IAChC,4BAA4B,CAAC,EAAE,MAAM,CAAA;CACtC,GACD,CAAC,SAAS,cAAc,GACtB;IAAE,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,IAAI,CAAA;CAAE,GAClD,CAAC,SAAS,gBAAgB,GACxB;IACE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,GACD,CAAC,SAAS,mBAAmB,GAC3B;IACE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC,GACD,CAAC,SAAS,cAAc,GACtB;IACE,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,GACD,CAAC,SAAS,cAAc,GACtB;IACE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,4BAA4B,CAAC,EAAE,MAAM,CAAA;CACtC,GACD,EAAE,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/mpc/keysign/chainSpecific/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qEAAqE,CAAA;AAC1G,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAEpC,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAA;AACnF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAEtF,KAAK,YAAY,CAAC,CAAC,SAAS,uBAAuB,IAAI,OAAO,CAAC,oBAAoB,EAAE;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC,CAAC,OAAO,CAAC,CAAA;AAE1G,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,uBAAuB,GAAG,uBAAuB,IAAI;IAC/F,cAAc,EAAE,cAAc,CAAA;IAC9B,UAAU,EAAE,UAAU,CAAA;IACtB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,GAAG,CAAC,CAAC,SAAS,kBAAkB,GAC7B;IACE,WAAW,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,CAAA;IAChC,4BAA4B,CAAC,EAAE,MAAM,CAAA;CACtC,GACD,CAAC,SAAS,cAAc,GACtB;IAAE,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,IAAI,CAAA;CAAE,GAClD,CAAC,SAAS,gBAAgB,GACxB;IACE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,GACD,CAAC,SAAS,mBAAmB,GAC3B;IACE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC,GACD,CAAC,SAAS,cAAc,GACtB;IACE,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,GACD,CAAC,SAAS,cAAc,GACtB;IACE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,4BAA4B,CAAC,EAAE,MAAM,CAAA;CACtC,GACD,CAAC,SAAS,gBAAgB,GACxB;IACE,mFAAmF;IACnF,eAAe,CAAC,EAAE,eAAe,CAAC,cAAc,GAAG,eAAe,CAAC,gBAAgB,CAAA;CACpF,GACD,CAAC,SAAS,aAAa,GACrB;IACE;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,GACD,EAAE,CAAC,CAAA;AAErB,MAAM,MAAM,wBAAwB,CAAC,CAAC,SAAS,uBAAuB,GAAG,uBAAuB,IAAI,QAAQ,CAC1G,qBAAqB,CAAC,CAAC,CAAC,EACxB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CACzB,CAAA"}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import { GetChainSpecificResolver } from '../resolver.js';
|
|
2
2
|
export declare const getRippleLastLedgerSequence: (ledgerCurrentIndex: number | undefined) => bigint;
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the per-ceremony XRPL fields — sequence, network fee, ledger
|
|
5
|
+
* validity window, destination tag and the operation discriminator — and
|
|
6
|
+
* refuses, before the user reviews anything, a transaction the ledger would
|
|
7
|
+
* apply without delivering: a Payment missing a required DestinationTag, a
|
|
8
|
+
* native send too small to activate a fresh destination, and an issued-currency
|
|
9
|
+
* Payment whose destination or issuer cannot receive it.
|
|
10
|
+
*
|
|
11
|
+
* Deterministic bad input surfaces as a [BuildKeysignPayloadError] so callers
|
|
12
|
+
* stop retrying; lookups that merely failed stay retryable.
|
|
13
|
+
*/
|
|
3
14
|
export declare const getRippleChainSpecific: GetChainSpecificResolver<'rippleSpecific'>;
|
|
4
15
|
//# sourceMappingURL=ripple.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/mpc/keysign/chainSpecific/resolvers/ripple.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ripple.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/mpc/keysign/chainSpecific/resolvers/ripple.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAmFtD,eAAO,MAAM,2BAA2B,GAAI,oBAAoB,MAAM,GAAG,SAAS,KAAG,MAMpF,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,EAAE,wBAAwB,CAAC,gBAAgB,CAsJ7E,CAAA"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { create } from '@bufbuild/protobuf';
|
|
2
2
|
import { getRippleAccountInfo } from '@vultisig/core-chain/chains/ripple/account/info';
|
|
3
|
+
import { getRippleAccountLines } from '@vultisig/core-chain/chains/ripple/account/lines';
|
|
4
|
+
import { parseRippleTokenId } from '@vultisig/core-chain/chains/ripple/issuedCurrency';
|
|
5
|
+
import { findRippleTrustLine } from '@vultisig/core-chain/chains/ripple/trustLine';
|
|
3
6
|
import { getRippleNetworkInfo } from '@vultisig/core-chain/chains/ripple/network/info';
|
|
4
7
|
import { RippleSpecificSchema, TransactionType, } from '@vultisig/core-mpc/types/vultisig/keysign/v1/blockchain_specific_pb';
|
|
5
8
|
import { shouldBePresent } from '@vultisig/lib-utils/assert/shouldBePresent';
|
|
6
|
-
import { attempt } from '@vultisig/lib-utils/attempt';
|
|
9
|
+
import { attempt, withFallback } from '@vultisig/lib-utils/attempt';
|
|
7
10
|
import { isInError } from '@vultisig/lib-utils/error/isInError';
|
|
8
11
|
import { maxBigInt } from '@vultisig/lib-utils/math/maxBigInt';
|
|
9
12
|
import { BuildKeysignPayloadError } from '../../error.js';
|
|
@@ -14,13 +17,74 @@ const minProtocolFee = 15n;
|
|
|
14
17
|
const baseFeeMultiplier = 2n;
|
|
15
18
|
const rippleRequireDestinationTagFlag = 0x00020000;
|
|
16
19
|
const lastLedgerSequenceOffset = 60;
|
|
20
|
+
/**
|
|
21
|
+
* `AccountRoot.TransferRate` encoding for "no transfer fee". The field is
|
|
22
|
+
* absent or zero on most issuers; anything above this billionths-denominated
|
|
23
|
+
* unit rate means the issuer charges a fee on every hop.
|
|
24
|
+
* @see https://xrpl.org/docs/concepts/tokens/transfer-fees
|
|
25
|
+
*/
|
|
26
|
+
const rippleNoTransferFeeRate = 1_000_000_000;
|
|
27
|
+
/**
|
|
28
|
+
* Rejects an issued-currency Payment the XRP Ledger would refuse to deliver,
|
|
29
|
+
* while the payload is still being built.
|
|
30
|
+
*
|
|
31
|
+
* Both shapes it catches are *applied* transactions on-ledger: the fee is
|
|
32
|
+
* burned and the sequence consumed even though nothing moves. A destination
|
|
33
|
+
* holding no trust line for the exact (currency, issuer) fails with
|
|
34
|
+
* tecNO_LINE/tecPATH_DRY, and an issuer charging a TransferRate fails with
|
|
35
|
+
* tecPATH_PARTIAL because the sender owes `Amount x (1 + rate)` while XRPL
|
|
36
|
+
* defaults SendMax to Amount alone.
|
|
37
|
+
*
|
|
38
|
+
* Fails closed: a lookup that does not come back is not evidence of a usable
|
|
39
|
+
* trust line, and those failures stay retryable rather than becoming a
|
|
40
|
+
* [BuildKeysignPayloadError].
|
|
41
|
+
*
|
|
42
|
+
* Not for redemptions — sending a token back to its own issuer needs no trust
|
|
43
|
+
* line and pays no transfer fee. Callers skip it in that case.
|
|
44
|
+
*/
|
|
45
|
+
const assertRippleTokenIsDeliverable = async ({ ticker, senderAddress, toAddress, issuedCurrency, }) => {
|
|
46
|
+
const [linesResult, issuerResult] = await Promise.all([
|
|
47
|
+
attempt(getRippleAccountLines(toAddress)),
|
|
48
|
+
// An issuer never charges itself a transfer fee on its own token.
|
|
49
|
+
senderAddress === issuedCurrency.issuer ? undefined : attempt(getRippleAccountInfo(issuedCurrency.issuer)),
|
|
50
|
+
]);
|
|
51
|
+
if ('error' in linesResult) {
|
|
52
|
+
throw new Error(`Unable to verify whether XRP destination ${toAddress} holds a trust line for ${ticker}`);
|
|
53
|
+
}
|
|
54
|
+
if (!findRippleTrustLine({ lines: linesResult.data, ...issuedCurrency })) {
|
|
55
|
+
throw new BuildKeysignPayloadError('ripple-destination-trust-line-missing', `Cannot send ${ticker} to ${toAddress}: that account holds no trust line for this token, ` +
|
|
56
|
+
'so the XRP Ledger would reject the payment. The recipient has to open one first.');
|
|
57
|
+
}
|
|
58
|
+
if (issuerResult === undefined) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if ('error' in issuerResult) {
|
|
62
|
+
throw new Error(`Unable to verify whether the ${ticker} issuer charges an XRP transfer fee`);
|
|
63
|
+
}
|
|
64
|
+
const { TransferRate } = issuerResult.data.account_data;
|
|
65
|
+
if (TransferRate !== undefined && TransferRate > rippleNoTransferFeeRate) {
|
|
66
|
+
throw new BuildKeysignPayloadError('ripple-issuer-transfer-fee-unsupported', `Cannot send ${ticker}: its issuer charges a transfer fee, which needs a SendMax this ` +
|
|
67
|
+
'payload cannot express yet. Sending it back to the issuer still works.');
|
|
68
|
+
}
|
|
69
|
+
};
|
|
17
70
|
export const getRippleLastLedgerSequence = (ledgerCurrentIndex) => {
|
|
18
71
|
if (ledgerCurrentIndex === undefined || !Number.isSafeInteger(ledgerCurrentIndex) || ledgerCurrentIndex <= 0) {
|
|
19
72
|
throw new Error('Ripple account_info response is missing a valid ledger_current_index.');
|
|
20
73
|
}
|
|
21
74
|
return BigInt(ledgerCurrentIndex + lastLedgerSequenceOffset);
|
|
22
75
|
};
|
|
23
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Resolves the per-ceremony XRPL fields — sequence, network fee, ledger
|
|
78
|
+
* validity window, destination tag and the operation discriminator — and
|
|
79
|
+
* refuses, before the user reviews anything, a transaction the ledger would
|
|
80
|
+
* apply without delivering: a Payment missing a required DestinationTag, a
|
|
81
|
+
* native send too small to activate a fresh destination, and an issued-currency
|
|
82
|
+
* Payment whose destination or issuer cannot receive it.
|
|
83
|
+
*
|
|
84
|
+
* Deterministic bad input surfaces as a [BuildKeysignPayloadError] so callers
|
|
85
|
+
* stop retrying; lookups that merely failed stay retryable.
|
|
86
|
+
*/
|
|
87
|
+
export const getRippleChainSpecific = async ({ keysignPayload, destinationTag, transactionType, }) => {
|
|
24
88
|
const coin = getKeysignCoin(keysignPayload);
|
|
25
89
|
const { address } = coin;
|
|
26
90
|
// A dApp-supplied transaction (OfferCreate, OfferCancel, …) carries no
|
|
@@ -32,6 +96,26 @@ export const getRippleChainSpecific = async ({ keysignPayload, destinationTag, }
|
|
|
32
96
|
destinationTag,
|
|
33
97
|
memo: keysignPayload.memo,
|
|
34
98
|
});
|
|
99
|
+
// Preserve existing trust-line callers, but an ordinary send explicitly
|
|
100
|
+
// selects Payment: sending tokens back to their issuer is also a Payment.
|
|
101
|
+
const isTrustSet = transactionType === undefined
|
|
102
|
+
? originatesRippleTrustSet(keysignPayload)
|
|
103
|
+
: transactionType === TransactionType.RIPPLE_TRUST_SET;
|
|
104
|
+
// A verbatim dApp transaction is signed exactly as supplied, so the token
|
|
105
|
+
// pre-flights below — which describe a Payment this resolver would build —
|
|
106
|
+
// do not apply to it.
|
|
107
|
+
const isVerbatimDappTx = keysignPayload.signData.case === 'signRipple';
|
|
108
|
+
const isIssuedCurrencySend = !isTrustSet && !isVerbatimDappTx && !!keysignPayload.coin && !keysignPayload.coin.isNativeToken;
|
|
109
|
+
// A payload with no parseable token id cannot name an asset to pre-flight.
|
|
110
|
+
// The signing-input resolver rejects that shape outright; here it only means
|
|
111
|
+
// there is nothing to look up.
|
|
112
|
+
const tokenId = isIssuedCurrencySend ? coin.id : undefined;
|
|
113
|
+
const issuedCurrency = tokenId
|
|
114
|
+
? withFallback(attempt(() => parseRippleTokenId(tokenId)), undefined)
|
|
115
|
+
: undefined;
|
|
116
|
+
// Sending a token back to its issuer redeems it: the issuer needs no trust
|
|
117
|
+
// line to itself and charges no transfer fee, so neither pre-flight applies.
|
|
118
|
+
const redeemsToIssuer = issuedCurrency !== undefined && toAddress === issuedCurrency.issuer;
|
|
35
119
|
const [senderAccount, networkInfo, destinationAccountResult] = await Promise.all([
|
|
36
120
|
getRippleAccountInfo(address),
|
|
37
121
|
getRippleNetworkInfo(),
|
|
@@ -54,7 +138,7 @@ export const getRippleChainSpecific = async ({ keysignPayload, destinationTag, }
|
|
|
54
138
|
// XRP Ledger rejects a Payment to an account with lsfRequireDestTag when no
|
|
55
139
|
// tag is present. Fail closed on lookup errors other than an unfunded
|
|
56
140
|
// destination: without an account object there is no RequireDestTag flag.
|
|
57
|
-
if (toAddress && destinationAccountResult !== undefined && !
|
|
141
|
+
if (toAddress && destinationAccountResult !== undefined && !isTrustSet && effectiveDestinationTag === undefined) {
|
|
58
142
|
if ('error' in destinationAccountResult) {
|
|
59
143
|
if (!destinationUnfunded) {
|
|
60
144
|
// This lookup can fail transiently, so keep it retryable. Only
|
|
@@ -67,6 +151,16 @@ export const getRippleChainSpecific = async ({ keysignPayload, destinationTag, }
|
|
|
67
151
|
}
|
|
68
152
|
}
|
|
69
153
|
if (destinationUnfunded) {
|
|
154
|
+
// A TrustSet is addressed to the issuer, not to a payee. Saying "activate
|
|
155
|
+
// it before sending tokens" would tell the user to fund somebody else's
|
|
156
|
+
// account; an issuer that does not exist simply cannot be trusted.
|
|
157
|
+
if (isTrustSet) {
|
|
158
|
+
throw new BuildKeysignPayloadError('ripple-trust-line-issuer-not-activated', `Cannot open an XRP trust line to ${toAddress}: that issuer account does not exist on the ledger.`);
|
|
159
|
+
}
|
|
160
|
+
if (!keysignPayload.coin?.isNativeToken) {
|
|
161
|
+
throw new BuildKeysignPayloadError('ripple-destination-not-activated', `Cannot send an XRP issued currency to ${toAddress}: the destination account is not activated. ` +
|
|
162
|
+
'Activate it with the XRP base reserve before sending tokens.');
|
|
163
|
+
}
|
|
70
164
|
const toAmount = BigInt(shouldBePresent(keysignPayload.toAmount));
|
|
71
165
|
if (toAmount < BigInt(reserve_base)) {
|
|
72
166
|
throw new Error(`Cannot send to XRP account ${toAddress}: it is not yet activated, and XRPL requires the ` +
|
|
@@ -75,6 +169,14 @@ export const getRippleChainSpecific = async ({ keysignPayload, destinationTag, }
|
|
|
75
169
|
`the reserve, or send to an already-activated account.`);
|
|
76
170
|
}
|
|
77
171
|
}
|
|
172
|
+
if (issuedCurrency && toAddress && !redeemsToIssuer) {
|
|
173
|
+
await assertRippleTokenIsDeliverable({
|
|
174
|
+
ticker: coin.ticker,
|
|
175
|
+
senderAddress: address,
|
|
176
|
+
toAddress,
|
|
177
|
+
issuedCurrency,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
78
180
|
const { account_data, ledger_current_index: ledgerCurrentIndex } = senderAccount;
|
|
79
181
|
// State the operation on the wire rather than leaving every signer to infer
|
|
80
182
|
// it from the coin. A non-native Ripple coin means either "open a trust line"
|
|
@@ -85,14 +187,17 @@ export const getRippleChainSpecific = async ({ keysignPayload, destinationTag, }
|
|
|
85
187
|
// Only genuine originations are declared. Stamping a token send would make
|
|
86
188
|
// every signer agree to build a TrustSet from it, which is worse than the
|
|
87
189
|
// divergence: the ceremony completes over an operation nobody asked for.
|
|
88
|
-
const isTrustSet = originatesRippleTrustSet(keysignPayload);
|
|
89
190
|
return create(RippleSpecificSchema, {
|
|
90
191
|
sequence: BigInt(account_data.Sequence),
|
|
91
192
|
lastLedgerSequence: getRippleLastLedgerSequence(ledgerCurrentIndex),
|
|
92
193
|
// Fee is the network fee only — the reserve rides on the Payment amount.
|
|
93
194
|
gas: networkFee,
|
|
94
195
|
...(effectiveDestinationTag !== undefined ? { destinationTag: effectiveDestinationTag } : {}),
|
|
95
|
-
...(isTrustSet
|
|
196
|
+
...(isTrustSet
|
|
197
|
+
? { transactionType: TransactionType.RIPPLE_TRUST_SET }
|
|
198
|
+
: transactionType === TransactionType.RIPPLE_PAYMENT
|
|
199
|
+
? { transactionType: TransactionType.RIPPLE_PAYMENT }
|
|
200
|
+
: {}),
|
|
96
201
|
});
|
|
97
202
|
};
|
|
98
203
|
//# sourceMappingURL=ripple.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ripple.js","sourceRoot":"","sources":["../../../../../../../packages/core/mpc/keysign/chainSpecific/resolvers/ripple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,iDAAiD,CAAA;AACtF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iDAAiD,CAAA;AACtF,OAAO,EACL,oBAAoB,EACpB,eAAe,GAChB,MAAM,qEAAqE,CAAA;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAA;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"ripple.js","sourceRoot":"","sources":["../../../../../../../packages/core/mpc/keysign/chainSpecific/resolvers/ripple.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/chainSpecific/resolvers/ton/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/chainSpecific/resolvers/ton/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAkCzD;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,EAAE,wBAAwB,CAAC,aAAa,CAyGvE,CAAA"}
|
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
import { create } from '@bufbuild/protobuf';
|
|
2
2
|
import { getTonAccountInfo } from '@vultisig/core-chain/chains/ton/account/getTonAccountInfo';
|
|
3
|
+
import { getTonAddressBounceability } from '@vultisig/core-chain/chains/ton/address';
|
|
3
4
|
import { getJettonWalletAddress, getTonWalletState } from '@vultisig/core-chain/chains/ton/api';
|
|
4
5
|
import { TonSpecificSchema } from '@vultisig/core-mpc/types/vultisig/keysign/v1/blockchain_specific_pb';
|
|
5
6
|
import { attempt } from '@vultisig/lib-utils/attempt';
|
|
7
|
+
import { getKeysignSwapPayload } from '../../../swap/getKeysignSwapPayload.js';
|
|
6
8
|
import { getKeysignCoin } from '../../../utils/getKeysignCoin.js';
|
|
7
9
|
const tonWalletStateUninitialized = 'uninit';
|
|
10
|
+
/** How long a wallet message stays valid when the caller sets no tighter deadline. */
|
|
11
|
+
const tonWalletExpirySeconds = 600;
|
|
12
|
+
/**
|
|
13
|
+
* The `expireAt` to sign. The wallet's own 10-minute window is the ceiling; a dApp
|
|
14
|
+
* deadline (`valid_until`) can only tighten it, never extend it. A deadline that has
|
|
15
|
+
* already passed by build time fails here rather than producing a transaction the
|
|
16
|
+
* network will reject.
|
|
17
|
+
*/
|
|
18
|
+
const resolveTonExpireAt = ({ now, validUntil }) => {
|
|
19
|
+
const walletDeadline = now + tonWalletExpirySeconds;
|
|
20
|
+
if (validUntil === undefined) {
|
|
21
|
+
return walletDeadline;
|
|
22
|
+
}
|
|
23
|
+
// Whole seconds only: flooring first means a deadline less than a second out is
|
|
24
|
+
// caught here rather than signed as an expiry equal to `now`.
|
|
25
|
+
const deadline = Number.isFinite(validUntil) ? Math.floor(validUntil) : Number.NaN;
|
|
26
|
+
if (!(deadline > now)) {
|
|
27
|
+
throw new Error(`TON request deadline (valid_until ${validUntil}) has already passed`);
|
|
28
|
+
}
|
|
29
|
+
return Math.min(walletDeadline, deadline);
|
|
30
|
+
};
|
|
8
31
|
/**
|
|
9
32
|
* Resolves the TON-specific keysign fields: the sender's seqno, an expiry, whether the
|
|
10
33
|
* transfer bounces on rejection, and — for Jettons — the sender's Jetton wallet and
|
|
@@ -12,7 +35,7 @@ const tonWalletStateUninitialized = 'uninit';
|
|
|
12
35
|
* rather than inferred, so an ordinary send that happens to sit close to the balance is
|
|
13
36
|
* not relabelled a MAX send.
|
|
14
37
|
*/
|
|
15
|
-
export const getTonChainSpecific = async ({ keysignPayload, sendMaxAmount = false, }) => {
|
|
38
|
+
export const getTonChainSpecific = async ({ keysignPayload, sendMaxAmount = false, validUntil, }) => {
|
|
16
39
|
const coin = getKeysignCoin(keysignPayload);
|
|
17
40
|
const { address } = coin;
|
|
18
41
|
const receiver = keysignPayload.toAddress;
|
|
@@ -27,31 +50,40 @@ export const getTonChainSpecific = async ({ keysignPayload, sendMaxAmount = fals
|
|
|
27
50
|
// than returning null and crashing this destructure.
|
|
28
51
|
const { account_state } = await getTonAccountInfo(address);
|
|
29
52
|
const sequenceNumber = BigInt(account_state?.seqno ?? 0);
|
|
53
|
+
// Whether the transfer goes out bounceable, which decides what happens to the funds
|
|
54
|
+
// when the destination rejects the message: a bounceable transfer is refunded, a
|
|
55
|
+
// non-bounceable one is absorbed by the destination and gone.
|
|
30
56
|
const getIsBounceable = async () => {
|
|
31
|
-
if (receiver) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
57
|
+
if (!receiver) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
// A swap deposit lands on a router or escrow contract, and there are ordinary
|
|
61
|
+
// reasons for such a contract to reject: an expired quote, a paused pool, a
|
|
62
|
+
// route that closed between quote and broadcast. Those have to come back.
|
|
63
|
+
if (getKeysignSwapPayload(keysignPayload)) {
|
|
64
|
+
return true;
|
|
37
65
|
}
|
|
38
|
-
|
|
66
|
+
// An undeployed account has no code to reject anything, so a bounceable message
|
|
67
|
+
// is simply returned and the transfer never lands. Those must go non-bounceable.
|
|
68
|
+
const { data: walletState } = await attempt(getTonWalletState(receiver));
|
|
69
|
+
if (walletState === tonWalletStateUninitialized) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
// A raw `0:hex` destination declares no intent, so it defaults to bounceable —
|
|
73
|
+
// the safe side for anything that might be a contract. Only an explicit `UQ…`
|
|
74
|
+
// opts out.
|
|
75
|
+
return getTonAddressBounceability(receiver) !== 'nonBounceable';
|
|
39
76
|
};
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// that address there is no transaction to build. Leaving the empty-string default
|
|
51
|
-
// in place does not stop anything downstream — the signing path's presence check
|
|
52
|
-
// only rejects null/undefined — so a failed lookup would otherwise be signed as a
|
|
53
|
-
// transfer to nowhere. This lookup fails transiently (RPC timeout, indexer lag),
|
|
54
|
-
// so it stays a plain retryable Error rather than a BuildKeysignPayloadError.
|
|
77
|
+
// A Jetton transfer is a message to the SENDER's own jetton wallet, so without
|
|
78
|
+
// that address there is no transaction to build. Leaving the empty-string default
|
|
79
|
+
// in place does not stop anything downstream — the signing path's presence check
|
|
80
|
+
// only rejects null/undefined — so a failed lookup would otherwise be signed as a
|
|
81
|
+
// transfer to nowhere. This lookup fails transiently (RPC timeout, indexer lag),
|
|
82
|
+
// so it stays a plain retryable Error rather than a BuildKeysignPayloadError.
|
|
83
|
+
const getJettonFields = async () => {
|
|
84
|
+
if (!coin.id) {
|
|
85
|
+
return { jettonAddress: '', isActiveDestination: false };
|
|
86
|
+
}
|
|
55
87
|
const jettonWallet = await attempt(getJettonWalletAddress({
|
|
56
88
|
ownerAddress: address,
|
|
57
89
|
jettonMasterAddress: coin.id,
|
|
@@ -60,12 +92,30 @@ export const getTonChainSpecific = async ({ keysignPayload, sendMaxAmount = fals
|
|
|
60
92
|
throw new Error(`Unable to resolve the ${coin.ticker} jetton wallet owned by ${address}. ` +
|
|
61
93
|
'Refusing to build a Jetton transfer without it.', 'error' in jettonWallet ? { cause: jettonWallet.error } : undefined);
|
|
62
94
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const { data: destWalletState } = await attempt(getTonWalletState(receiver));
|
|
66
|
-
result.isActiveDestination = destWalletState !== tonWalletStateUninitialized;
|
|
95
|
+
if (!receiver) {
|
|
96
|
+
return { jettonAddress: jettonWallet.data, isActiveDestination: false };
|
|
67
97
|
}
|
|
68
|
-
|
|
69
|
-
|
|
98
|
+
const { data: destWalletState } = await attempt(getTonWalletState(receiver));
|
|
99
|
+
return {
|
|
100
|
+
jettonAddress: jettonWallet.data,
|
|
101
|
+
isActiveDestination: destWalletState !== tonWalletStateUninitialized,
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
const bounceable = await getIsBounceable();
|
|
105
|
+
const { jettonAddress, isActiveDestination } = await getJettonFields();
|
|
106
|
+
// Read the clock last. Every lookup above is a network round trip, and a deadline
|
|
107
|
+
// that was still ahead when the build started can be behind by the time it
|
|
108
|
+
// finishes — computing the expiry up front would sign that dead deadline instead
|
|
109
|
+
// of refusing it, and would also spend part of the wallet's own ten-minute window
|
|
110
|
+
// on the lookups.
|
|
111
|
+
const expireAt = BigInt(resolveTonExpireAt({ now: Math.floor(Date.now() / 1000), validUntil }));
|
|
112
|
+
return create(TonSpecificSchema, {
|
|
113
|
+
sequenceNumber,
|
|
114
|
+
expireAt,
|
|
115
|
+
bounceable,
|
|
116
|
+
sendMaxAmount,
|
|
117
|
+
jettonAddress,
|
|
118
|
+
isActiveDestination,
|
|
119
|
+
});
|
|
70
120
|
};
|
|
71
121
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/chainSpecific/resolvers/ton/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2DAA2D,CAAA;AAC7F,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,qEAAqE,CAAA;AACvG,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAG9D,MAAM,2BAA2B,GAAG,QAAQ,CAAA;AAE5C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA4C,KAAK,EAAE,EACjF,cAAc,EACd,aAAa,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/chainSpecific/resolvers/ton/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
import { getTronBlockInfo } from '@vultisig/core-chain/chains/tron/getTronBlockInfo';
|
|
2
|
+
import { type WalletCore } from '@trustwallet/wallet-core';
|
|
1
3
|
import { GetChainSpecificResolver } from '../../resolver.js';
|
|
4
|
+
type NativeTronBandwidthInput = {
|
|
5
|
+
walletCore: WalletCore;
|
|
6
|
+
fromAddress: string;
|
|
7
|
+
toAddress: string;
|
|
8
|
+
amount: bigint;
|
|
9
|
+
memo: string;
|
|
10
|
+
blockInfo: Awaited<ReturnType<typeof getTronBlockInfo>>;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* TRON charges bandwidth for the serialized signed transaction, not for a
|
|
14
|
+
* fixed transfer template. WalletCore exposes the exact raw_data bytes through
|
|
15
|
+
* its pre-signing output; the remaining signed envelope consists of the
|
|
16
|
+
* length-delimited raw_data field and one 65-byte secp256k1 signature.
|
|
17
|
+
*/
|
|
18
|
+
export declare const getNativeTronBandwidthBytes: ({ walletCore, fromAddress, toAddress, amount, memo, blockInfo, }: NativeTronBandwidthInput) => number;
|
|
2
19
|
export declare const getTronChainSpecific: GetChainSpecificResolver<'tronSpecific'>;
|
|
20
|
+
export {};
|
|
3
21
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/chainSpecific/resolvers/tron/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/chainSpecific/resolvers/tron/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mDAAmD,CAAA;AAKpF,OAAO,EAAM,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAK9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AA0BzD,KAAK,wBAAwB,GAAG;IAC9B,UAAU,EAAE,UAAU,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAA;CACxD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,GAAI,kEAOzC,wBAAwB,KAAG,MAqC7B,CAAA;AAgBD,eAAO,MAAM,oBAAoB,EAAE,wBAAwB,CAAC,cAAc,CAmDzE,CAAA"}
|