@vultisig/core-mpc 1.12.0 → 1.12.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 +43 -0
- package/dist/chains/cosmos/qbtc/QBTCHelper.js +11 -0
- package/dist/chains/cosmos/qbtc/QBTCHelper.js.map +1 -1
- package/dist/chains/cosmos/qbtc/QBTCTx.d.ts +1 -1
- package/dist/chains/cosmos/qbtc/QBTCTx.d.ts.map +1 -1
- package/dist/chains/cosmos/qbtc/QBTCTx.js +8 -2
- package/dist/chains/cosmos/qbtc/QBTCTx.js.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/cosmos/index.d.ts.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/cosmos/index.js +6 -4
- package/dist/keysign/chainSpecific/resolvers/cosmos/index.js.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/maya.js +2 -2
- package/dist/keysign/chainSpecific/resolvers/maya.js.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/sui/index.d.ts.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/sui/index.js +51 -6
- package/dist/keysign/chainSpecific/resolvers/sui/index.js.map +1 -1
- package/dist/keysign/chainSpecific/resolvers/thor.js +2 -2
- package/dist/keysign/chainSpecific/resolvers/thor.js.map +1 -1
- package/dist/keysign/signingInputs/index.d.ts.map +1 -1
- package/dist/keysign/signingInputs/index.js +12 -0
- package/dist/keysign/signingInputs/index.js.map +1 -1
- package/dist/keysign/signingInputs/resolvers/cardano.d.ts.map +1 -1
- package/dist/keysign/signingInputs/resolvers/cardano.js +17 -2
- package/dist/keysign/signingInputs/resolvers/cardano.js.map +1 -1
- package/dist/keysign/signingInputs/resolvers/evm/index.d.ts.map +1 -1
- package/dist/keysign/signingInputs/resolvers/evm/index.js +37 -0
- package/dist/keysign/signingInputs/resolvers/evm/index.js.map +1 -1
- package/dist/keysign/signingInputs/resolvers/solana/index.d.ts.map +1 -1
- package/dist/keysign/signingInputs/resolvers/solana/index.js +43 -14
- package/dist/keysign/signingInputs/resolvers/solana/index.js.map +1 -1
- package/dist/keysign/signingInputs/resolvers/solana/rawTx.d.ts +52 -0
- package/dist/keysign/signingInputs/resolvers/solana/rawTx.d.ts.map +1 -0
- package/dist/keysign/signingInputs/resolvers/solana/rawTx.js +84 -0
- package/dist/keysign/signingInputs/resolvers/solana/rawTx.js.map +1 -0
- package/dist/keysign/signingInputs/resolvers/sui.d.ts.map +1 -1
- package/dist/keysign/signingInputs/resolvers/sui.js +13 -6
- package/dist/keysign/signingInputs/resolvers/sui.js.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ton/jetton.d.ts.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ton/jetton.js +4 -6
- package/dist/keysign/signingInputs/resolvers/ton/jetton.js.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ton/native.d.ts +2 -0
- package/dist/keysign/signingInputs/resolvers/ton/native.d.ts.map +1 -1
- package/dist/keysign/signingInputs/resolvers/ton/native.js +25 -4
- package/dist/keysign/signingInputs/resolvers/ton/native.js.map +1 -1
- package/dist/keysign/suiCoinSelection.d.ts +20 -0
- package/dist/keysign/suiCoinSelection.d.ts.map +1 -0
- package/dist/keysign/suiCoinSelection.js +88 -0
- package/dist/keysign/suiCoinSelection.js.map +1 -0
- package/dist/keysign/swap/assertNativeSwapReadyForBroadcast.d.ts +26 -0
- package/dist/keysign/swap/assertNativeSwapReadyForBroadcast.d.ts.map +1 -0
- package/dist/keysign/swap/assertNativeSwapReadyForBroadcast.js +96 -0
- package/dist/keysign/swap/assertNativeSwapReadyForBroadcast.js.map +1 -0
- package/dist/keysign/swap/build.d.ts.map +1 -1
- package/dist/keysign/swap/build.js +5 -1
- package/dist/keysign/swap/build.js.map +1 -1
- package/dist/security/blockaid/tx/utils/getCompiledTxsForBlockaidInput.d.ts.map +1 -1
- package/dist/security/blockaid/tx/utils/getCompiledTxsForBlockaidInput.js +12 -0
- package/dist/security/blockaid/tx/utils/getCompiledTxsForBlockaidInput.js.map +1 -1
- package/dist/swap/utils/getSwapTrackingUrl.d.ts.map +1 -1
- package/dist/swap/utils/getSwapTrackingUrl.js +5 -60
- package/dist/swap/utils/getSwapTrackingUrl.js.map +1 -1
- package/dist/tx/compile/compileTx.d.ts.map +1 -1
- package/dist/tx/compile/compileTx.js +28 -0
- package/dist/tx/compile/compileTx.js.map +1 -1
- package/dist/tx/preSigningHashes/index.d.ts.map +1 -1
- package/dist/tx/preSigningHashes/index.js +10 -0
- package/dist/tx/preSigningHashes/index.js.map +1 -1
- package/package.json +18 -3
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { Buffer } from 'buffer';
|
|
2
|
+
import { assertSafeSolanaSwapTransactionBase64 } from '@vultisig/core-chain/chains/solana/assertSafeSolanaSwapInstructions';
|
|
2
3
|
import { getCoinType } from '@vultisig/core-chain/coin/coinType';
|
|
4
|
+
import { assertField } from '@vultisig/lib-utils/record/assertField';
|
|
3
5
|
import { shouldBePresent } from '@vultisig/lib-utils/assert/shouldBePresent';
|
|
4
6
|
import { matchRecordUnion } from '@vultisig/lib-utils/matchRecordUnion';
|
|
7
|
+
import { PublicKey } from '@solana/web3.js';
|
|
5
8
|
import { TW } from '@trustwallet/wallet-core';
|
|
6
9
|
import { getBlockchainSpecificValue } from '../../../chainSpecific/KeysignChainSpecific.js';
|
|
7
10
|
import { getKeysignSwapPayload } from '../../../swap/getKeysignSwapPayload.js';
|
|
@@ -11,27 +14,53 @@ export const getSolanaSigningInputs = ({ keysignPayload, walletCore }) => {
|
|
|
11
14
|
const chain = getKeysignChain(keysignPayload);
|
|
12
15
|
const { recentBlockHash } = getBlockchainSpecificValue(keysignPayload.blockchainSpecific, 'solanaSpecific');
|
|
13
16
|
if (keysignPayload.signData.case === 'signSolana') {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return TW.Solana.Proto.SigningInput.create({
|
|
23
|
-
rawMessage,
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
return inputs;
|
|
17
|
+
// Handled upstream in getEncodedSigningInputs (sdk#1204): dApp raw
|
|
18
|
+
// transactions are signed over their ORIGINAL message bytes and never
|
|
19
|
+
// routed through TransactionDecoder + SigningInput.rawMessage — the
|
|
20
|
+
// WalletCore re-encode is not byte-identical for v0+ALT transactions
|
|
21
|
+
// and breaks mixed-vault co-signing (ios#4419, android#5223). Reaching
|
|
22
|
+
// this branch means a caller bypassed getEncodedSigningInputs; fail
|
|
23
|
+
// loud instead of silently re-introducing the divergent pre-image.
|
|
24
|
+
throw new Error('signSolana raw transactions are handled in getEncodedSigningInputs — do not resolve them into TW SigningInputs (sdk#1204)');
|
|
27
25
|
}
|
|
28
26
|
const swapPayload = getKeysignSwapPayload(keysignPayload);
|
|
29
27
|
if (swapPayload) {
|
|
30
28
|
return matchRecordUnion(swapPayload, {
|
|
31
29
|
native: () => [getSolanaSendSigningInput({ keysignPayload, walletCore })],
|
|
32
|
-
general: swapPayload => {
|
|
30
|
+
general: async (swapPayload) => {
|
|
33
31
|
const tx = shouldBePresent(swapPayload.quote?.tx);
|
|
34
32
|
const { data } = tx;
|
|
33
|
+
// sdk#1358 fund-safety: re-run the Jupiter program allow-list + fund-movement guard HERE, on
|
|
34
|
+
// the co-signer signing-input path, not only at quote construction. Every co-signer (e.g.
|
|
35
|
+
// VultiServer in a 2-of-2) independently rebuilds this input from the shared KeysignPayload and
|
|
36
|
+
// signs it verbatim (only recentBlockhash is overwritten below), so a compromised initiator
|
|
37
|
+
// could otherwise slip a drain instruction into swapPayload.quote.tx.data that no co-signer ever
|
|
38
|
+
// validated. This is a PURE gate - it throws (fail-closed, like the Ripple resolver) or no-ops,
|
|
39
|
+
// and never touches the bytes that get signed, so it cannot desync the cross-device pre-signing
|
|
40
|
+
// hash. userWallet is the signing vault's own Solana address (coin.address).
|
|
41
|
+
//
|
|
42
|
+
// JUPITER-SCOPED on purpose: the allow-list (JUPITER_SWAP_ALLOWED_PROGRAM_IDS) is Jupiter's
|
|
43
|
+
// program set, and the only quote-time caller is getJupiterSwapQuote. LiFi and SwapKit also
|
|
44
|
+
// route Solana swaps (lifiSwapEnabledChains / swapKitEnabledChains include Chain.Solana) through
|
|
45
|
+
// Raydium/Orca/executor + fee-transfer instructions that are NOT in that set - guarding those
|
|
46
|
+
// here would fail-closed on a legitimate swap and brick the keysign. Mirrors the EVM arm, which
|
|
47
|
+
// only enforces the providers whose router is actually allow-listed.
|
|
48
|
+
//
|
|
49
|
+
// TRUST OF `provider` (same boundary the EVM arm documents in knownAggregatorRouters.ts): this
|
|
50
|
+
// is the free `provider` STRING on the OneInchSwapPayload proto, part of the attacker-influenceable
|
|
51
|
+
// payload, NOT a trusted oneof discriminant. So an attacker can embed a Jupiter tx in
|
|
52
|
+
// quote.tx.data but relabel `provider` to a non-jupiter value (or omit it -> '') to skip this
|
|
53
|
+
// guard. That is NOT a new bypass: this gate is MONOTONIC (throws or no-ops, never mutates the
|
|
54
|
+
// signed bytes), so skipping it merely degrades to the pre-#1358 state where no Solana
|
|
55
|
+
// signing-path guard ran at all - a payload that was unsignable before is not made signable. What
|
|
56
|
+
// the guard buys is defense against the realistic partial compromise the issue targets: a quote
|
|
57
|
+
// server/MITM that swaps quote.tx.data but leaves an honestly-declared `provider: 'jupiter'`
|
|
58
|
+
// intact. Complete co-signer protection would need a proto change (a distinct oneof case per
|
|
59
|
+
// provider) to key enforcement on the case rather than the string - out of scope, not a regression.
|
|
60
|
+
if (swapPayload.provider === 'jupiter') {
|
|
61
|
+
const userWallet = new PublicKey(assertField(keysignPayload, 'coin').address);
|
|
62
|
+
await assertSafeSolanaSwapTransactionBase64(data, userWallet);
|
|
63
|
+
}
|
|
35
64
|
const decodedData = walletCore.TransactionDecoder.decode(getCoinType({
|
|
36
65
|
walletCore,
|
|
37
66
|
chain,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/solana/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAA;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAA;AACvE,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAA;AAE7C,OAAO,EAAE,0BAA0B,EAAE,MAAM,6CAA6C,CAAA;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAA;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAEhE,OAAO,EAAE,yBAAyB,EAAE,MAAM,QAAQ,CAAA;AAElD,MAAM,CAAC,MAAM,sBAAsB,GAAoC,CAAC,EAAE,cAAc,EAAE,UAAU,EAAE,EAAE,EAAE;IACxG,MAAM,KAAK,GAAG,eAAe,CAAC,cAAc,CAAC,CAAA;IAE7C,MAAM,EAAE,eAAe,EAAE,GAAG,0BAA0B,CAAC,cAAc,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAA;IAE3G,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAClD,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/solana/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dApp-supplied raw Solana transaction handling (sdk#1204).
|
|
3
|
+
*
|
|
4
|
+
* For `signData.signSolana` transactions we sign the message bytes directly
|
|
5
|
+
* instead of routing through `SolanaSigningInput.rawMessage` +
|
|
6
|
+
* `TransactionCompiler`. The round-trip through WalletCore's proto re-encoder
|
|
7
|
+
* is sensitive to WalletCore version differences between platforms — even a
|
|
8
|
+
* one-byte drift in the re-encoded message (v0 + address-lookup-table
|
|
9
|
+
* transactions are the known-risky shape) produces a different pre-image,
|
|
10
|
+
* which breaks Secure Vault co-signing: the other party computes a different
|
|
11
|
+
* hash, the setup-message equality check throws, and no TSS messages are ever
|
|
12
|
+
* emitted. For Solana, ed25519 signs the wire-format message verbatim, so
|
|
13
|
+
* extracting it directly is canonical and cross-platform safe.
|
|
14
|
+
*
|
|
15
|
+
* Byte-for-byte port of vultisig-ios#4419 (`Solana.swift`
|
|
16
|
+
* `extractSolanaMessageBytes` / `signRawTransaction`); Android sibling is
|
|
17
|
+
* vultisig-android#5223. Wire format of a serialized Solana transaction:
|
|
18
|
+
*
|
|
19
|
+
* [shortvec(numSignatures)][numSignatures x 64-byte signature][message]
|
|
20
|
+
*/
|
|
21
|
+
export type ParsedSolanaRawTx = {
|
|
22
|
+
/** Byte offset of the first (fee payer, signer index 0) signature slot. */
|
|
23
|
+
firstSignatureOffset: number;
|
|
24
|
+
/** Declared signature-slot count from the shortvec envelope. */
|
|
25
|
+
numSignatures: number;
|
|
26
|
+
/** The Solana wire-format message bytes — the exact ed25519 pre-image. */
|
|
27
|
+
message: Uint8Array;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Strip the `[shortvec(numSigs)][numSigs x 64-byte sig]` envelope and return
|
|
31
|
+
* the underlying Solana message bytes plus the offset of the first signature
|
|
32
|
+
* slot (for later splice-in).
|
|
33
|
+
*/
|
|
34
|
+
export declare function extractSolanaMessageBytes(txData: Uint8Array): ParsedSolanaRawTx;
|
|
35
|
+
/**
|
|
36
|
+
* Splice the 64-byte signature into the original transaction at signer
|
|
37
|
+
* index 0 (the dApp builds the tx with the user as fee payer == first
|
|
38
|
+
* signer; any other signature slots stay as the dApp-provided placeholders).
|
|
39
|
+
* Returns a new array — the input is not mutated.
|
|
40
|
+
*
|
|
41
|
+
* Assumes the vault is signer index 0. Byte-for-byte parity with
|
|
42
|
+
* vultisig-ios#4419, which makes the same assumption. A sponsored
|
|
43
|
+
* transaction (a relayer pays and is signer 0, the vault signs at index
|
|
44
|
+
* >= 1) would land the vault's signature in the wrong slot — not
|
|
45
|
+
* fund-unsafe (the signature still binds the exact message it was
|
|
46
|
+
* computed over, so a misplaced signature just fails Solana's runtime
|
|
47
|
+
* signature check), but the tx would be rejected on broadcast rather
|
|
48
|
+
* than land. No sponsored-tx path exists today; if one is added, this
|
|
49
|
+
* splice needs the vault's actual signer index, not a hardcoded 0.
|
|
50
|
+
*/
|
|
51
|
+
export declare function spliceSolanaSignature(txData: Uint8Array, signature: Uint8Array): Uint8Array;
|
|
52
|
+
//# sourceMappingURL=rawTx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rawTx.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/solana/rawTx.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,2EAA2E;IAC3E,oBAAoB,EAAE,MAAM,CAAA;IAC5B,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAA;IACrB,0EAA0E;IAC1E,OAAO,EAAE,UAAU,CAAA;CACpB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,UAAU,GAAG,iBAAiB,CA4B/E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,UAAU,CAW3F"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dApp-supplied raw Solana transaction handling (sdk#1204).
|
|
3
|
+
*
|
|
4
|
+
* For `signData.signSolana` transactions we sign the message bytes directly
|
|
5
|
+
* instead of routing through `SolanaSigningInput.rawMessage` +
|
|
6
|
+
* `TransactionCompiler`. The round-trip through WalletCore's proto re-encoder
|
|
7
|
+
* is sensitive to WalletCore version differences between platforms — even a
|
|
8
|
+
* one-byte drift in the re-encoded message (v0 + address-lookup-table
|
|
9
|
+
* transactions are the known-risky shape) produces a different pre-image,
|
|
10
|
+
* which breaks Secure Vault co-signing: the other party computes a different
|
|
11
|
+
* hash, the setup-message equality check throws, and no TSS messages are ever
|
|
12
|
+
* emitted. For Solana, ed25519 signs the wire-format message verbatim, so
|
|
13
|
+
* extracting it directly is canonical and cross-platform safe.
|
|
14
|
+
*
|
|
15
|
+
* Byte-for-byte port of vultisig-ios#4419 (`Solana.swift`
|
|
16
|
+
* `extractSolanaMessageBytes` / `signRawTransaction`); Android sibling is
|
|
17
|
+
* vultisig-android#5223. Wire format of a serialized Solana transaction:
|
|
18
|
+
*
|
|
19
|
+
* [shortvec(numSignatures)][numSignatures x 64-byte signature][message]
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Strip the `[shortvec(numSigs)][numSigs x 64-byte sig]` envelope and return
|
|
23
|
+
* the underlying Solana message bytes plus the offset of the first signature
|
|
24
|
+
* slot (for later splice-in).
|
|
25
|
+
*/
|
|
26
|
+
export function extractSolanaMessageBytes(txData) {
|
|
27
|
+
let offset = 0;
|
|
28
|
+
let numSigs = 0;
|
|
29
|
+
let shift = 0;
|
|
30
|
+
// Solana compact-u16 (shortvec) decode: 7 bits per byte, high bit = continuation.
|
|
31
|
+
while (offset < txData.length) {
|
|
32
|
+
const byte = txData[offset];
|
|
33
|
+
numSigs |= (byte & 0x7f) << shift;
|
|
34
|
+
offset += 1;
|
|
35
|
+
if ((byte & 0x80) === 0)
|
|
36
|
+
break;
|
|
37
|
+
shift += 7;
|
|
38
|
+
if (shift > 14) {
|
|
39
|
+
throw new Error('Invalid shortvec for signature count');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (numSigs < 1) {
|
|
43
|
+
throw new Error('Transaction declares no signatures');
|
|
44
|
+
}
|
|
45
|
+
const firstSignatureOffset = offset;
|
|
46
|
+
const messageOffset = offset + numSigs * 64;
|
|
47
|
+
if (messageOffset >= txData.length) {
|
|
48
|
+
throw new Error(`Transaction too short for declared signature count (${numSigs})`);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
firstSignatureOffset,
|
|
52
|
+
numSignatures: numSigs,
|
|
53
|
+
message: txData.slice(messageOffset),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Splice the 64-byte signature into the original transaction at signer
|
|
58
|
+
* index 0 (the dApp builds the tx with the user as fee payer == first
|
|
59
|
+
* signer; any other signature slots stay as the dApp-provided placeholders).
|
|
60
|
+
* Returns a new array — the input is not mutated.
|
|
61
|
+
*
|
|
62
|
+
* Assumes the vault is signer index 0. Byte-for-byte parity with
|
|
63
|
+
* vultisig-ios#4419, which makes the same assumption. A sponsored
|
|
64
|
+
* transaction (a relayer pays and is signer 0, the vault signs at index
|
|
65
|
+
* >= 1) would land the vault's signature in the wrong slot — not
|
|
66
|
+
* fund-unsafe (the signature still binds the exact message it was
|
|
67
|
+
* computed over, so a misplaced signature just fails Solana's runtime
|
|
68
|
+
* signature check), but the tx would be rejected on broadcast rather
|
|
69
|
+
* than land. No sponsored-tx path exists today; if one is added, this
|
|
70
|
+
* splice needs the vault's actual signer index, not a hardcoded 0.
|
|
71
|
+
*/
|
|
72
|
+
export function spliceSolanaSignature(txData, signature) {
|
|
73
|
+
if (signature.length !== 64) {
|
|
74
|
+
throw new Error(`Solana signature must be 64 bytes, got ${signature.length}`);
|
|
75
|
+
}
|
|
76
|
+
const { firstSignatureOffset } = extractSolanaMessageBytes(txData);
|
|
77
|
+
if (firstSignatureOffset + 64 > txData.length) {
|
|
78
|
+
throw new Error('Transaction too short to place signature');
|
|
79
|
+
}
|
|
80
|
+
const signedTx = new Uint8Array(txData);
|
|
81
|
+
signedTx.set(signature, firstSignatureOffset);
|
|
82
|
+
return signedTx;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=rawTx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rawTx.js","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/solana/rawTx.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAWH;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAkB;IAC1D,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,kFAAkF;IAClF,OAAO,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;QAC3B,OAAO,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,CAAA;QACjC,MAAM,IAAI,CAAC,CAAA;QACX,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;YAAE,MAAK;QAC9B,KAAK,IAAI,CAAC,CAAA;QACV,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;QACzD,CAAC;IACH,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IACvD,CAAC;IACD,MAAM,oBAAoB,GAAG,MAAM,CAAA;IACnC,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,EAAE,CAAA;IAC3C,IAAI,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,uDAAuD,OAAO,GAAG,CAAC,CAAA;IACpF,CAAC;IACD,OAAO;QACL,oBAAoB;QACpB,aAAa,EAAE,OAAO;QACtB,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC;KACrC,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAkB,EAAE,SAAqB;IAC7E,IAAI,SAAS,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,0CAA0C,SAAS,CAAC,MAAM,EAAE,CAAC,CAAA;IAC/E,CAAC;IACD,MAAM,EAAE,oBAAoB,EAAE,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAA;IAClE,IAAI,oBAAoB,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;IAC7D,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAA;IACvC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAA;IAC7C,OAAO,QAAQ,CAAA;AACjB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sui.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/sui.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sui.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/sui.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEnD,eAAO,MAAM,mBAAmB,EAAE,qBAAqB,CAAC,KAAK,CAmF5D,CAAA"}
|
|
@@ -2,8 +2,8 @@ import { suiGasBudget } from '@vultisig/core-chain/chains/sui/config';
|
|
|
2
2
|
import { TW } from '@trustwallet/wallet-core';
|
|
3
3
|
import Long from 'long';
|
|
4
4
|
import { getBlockchainSpecificValue } from '../../chainSpecific/KeysignChainSpecific.js';
|
|
5
|
+
import { isNativeSuiCoin, isSameSuiCoinType, selectSuiGasObject, selectSuiInputCoins, suiNativeCoinType, } from '../../suiCoinSelection.js';
|
|
5
6
|
import { getKeysignCoin } from '../../utils/getKeysignCoin.js';
|
|
6
|
-
const suiContractAddress = '0x2::sui::SUI';
|
|
7
7
|
export const getSuiSigningInputs = ({ keysignPayload }) => {
|
|
8
8
|
const coin = getKeysignCoin(keysignPayload);
|
|
9
9
|
// dApp-supplied PTBs (Sui Wallet Standard) arrive already BCS-serialized in
|
|
@@ -28,25 +28,31 @@ export const getSuiSigningInputs = ({ keysignPayload }) => {
|
|
|
28
28
|
throw new Error('Sui transactions do not support a memo');
|
|
29
29
|
}
|
|
30
30
|
const { coins, referenceGasPrice, gasBudget } = getBlockchainSpecificValue(keysignPayload.blockchainSpecific, 'suicheSpecific');
|
|
31
|
-
const coinType = coin.id ||
|
|
31
|
+
const coinType = coin.id || suiNativeCoinType;
|
|
32
32
|
const createObjectRef = (coin) => TW.Sui.Proto.ObjectRef.create({
|
|
33
33
|
objectDigest: coin.digest,
|
|
34
34
|
objectId: coin.coinObjectId,
|
|
35
35
|
version: Long.fromString(coin.version),
|
|
36
36
|
});
|
|
37
|
-
const
|
|
37
|
+
const gasBudgetAmount = gasBudget ? BigInt(gasBudget) : suiGasBudget;
|
|
38
38
|
const baseInput = {
|
|
39
39
|
referenceGasPrice: Long.fromString(referenceGasPrice),
|
|
40
40
|
signer: coin.address,
|
|
41
|
-
gasBudget:
|
|
41
|
+
gasBudget: Long.fromString(gasBudgetAmount.toString()),
|
|
42
42
|
};
|
|
43
|
-
const
|
|
43
|
+
const amount = BigInt(keysignPayload.toAmount || '0');
|
|
44
44
|
if (coin.id) {
|
|
45
|
+
const tokenCoins = coins.filter(c => isSameSuiCoinType(c.coinType, coinType));
|
|
46
|
+
const inputCoins = selectSuiInputCoins(tokenCoins, amount).map(createObjectRef);
|
|
47
|
+
const gasObject = selectSuiGasObject(coins, gasBudgetAmount);
|
|
48
|
+
if (!gasObject) {
|
|
49
|
+
throw new Error('Non-native Sui token transaction requires at least one SUI coin for gas fees');
|
|
50
|
+
}
|
|
45
51
|
return [
|
|
46
52
|
TW.Sui.Proto.SigningInput.create({
|
|
47
53
|
...baseInput,
|
|
48
54
|
pay: TW.Sui.Proto.Pay.create({
|
|
49
|
-
gas:
|
|
55
|
+
gas: createObjectRef(gasObject),
|
|
50
56
|
inputCoins: inputCoins,
|
|
51
57
|
recipients: [keysignPayload.toAddress],
|
|
52
58
|
amounts: [Long.fromString(keysignPayload.toAmount)],
|
|
@@ -54,6 +60,7 @@ export const getSuiSigningInputs = ({ keysignPayload }) => {
|
|
|
54
60
|
}),
|
|
55
61
|
];
|
|
56
62
|
}
|
|
63
|
+
const inputCoins = selectSuiInputCoins(coins.filter(isNativeSuiCoin), amount + gasBudgetAmount).map(createObjectRef);
|
|
57
64
|
return [
|
|
58
65
|
TW.Sui.Proto.SigningInput.create({
|
|
59
66
|
...baseInput,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sui.js","sourceRoot":"","sources":["../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/sui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AAErE,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAA;AAC7C,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAA;AACrF,OAAO,
|
|
1
|
+
{"version":3,"file":"sui.js","sourceRoot":"","sources":["../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/sui.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jetton.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/ton/jetton.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"jetton.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/ton/jetton.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,iEAAiE,CAAA;AAEhG,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAMrD,KAAK,wBAAwB,GAAG;IAC9B,cAAc,EAAE,cAAc,CAAA;IAC9B,UAAU,EAAE,UAAU,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,mBAAmB,EAAE,OAAO,CAAA;CAC7B,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,qEAKjC,wBAAwB,KAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,QAyBrD,CAAA"}
|
|
@@ -1,25 +1,23 @@
|
|
|
1
|
-
import { Buffer } from 'buffer';
|
|
2
1
|
import { tonConfig } from '@vultisig/core-chain/chains/ton/config';
|
|
3
2
|
import { shouldBePresent } from '@vultisig/lib-utils/assert/shouldBePresent';
|
|
4
|
-
import { numberToEvenHex } from '@vultisig/lib-utils/hex/numberToHex';
|
|
5
3
|
import { TW } from '@trustwallet/wallet-core';
|
|
6
4
|
import { getKeysignAmount } from '../../../utils/getKeysignAmount.js';
|
|
7
5
|
import { getKeysignCoin } from '../../../utils/getKeysignCoin.js';
|
|
8
|
-
import { toSafeComment } from './native.js';
|
|
6
|
+
import { toSafeComment, tonAmountToBytes } from './native.js';
|
|
9
7
|
export const buildJettonTransfer = ({ keysignPayload, walletCore, jettonAddress, isActiveDestination, }) => {
|
|
10
8
|
const coin = getKeysignCoin(keysignPayload);
|
|
11
9
|
const destinationAddress = walletCore.TONAddressConverter.toUserFriendly(keysignPayload.toAddress, true, false);
|
|
12
10
|
const forwardAmount = isActiveDestination ? 1n : 0n;
|
|
13
11
|
const jettonTransfer = TW.TheOpenNetwork.Proto.JettonTransfer.create({
|
|
14
|
-
jettonAmount:
|
|
12
|
+
jettonAmount: tonAmountToBytes(shouldBePresent(getKeysignAmount(keysignPayload))),
|
|
15
13
|
toOwner: destinationAddress,
|
|
16
14
|
responseAddress: coin.address,
|
|
17
|
-
forwardAmount:
|
|
15
|
+
forwardAmount: tonAmountToBytes(forwardAmount),
|
|
18
16
|
});
|
|
19
17
|
const mode = TW.TheOpenNetwork.Proto.SendMode.PAY_FEES_SEPARATELY | TW.TheOpenNetwork.Proto.SendMode.IGNORE_ACTION_PHASE_ERRORS;
|
|
20
18
|
return TW.TheOpenNetwork.Proto.Transfer.create({
|
|
21
19
|
dest: jettonAddress,
|
|
22
|
-
amount:
|
|
20
|
+
amount: tonAmountToBytes(tonConfig.jettonAmount),
|
|
23
21
|
bounceable: true,
|
|
24
22
|
comment: toSafeComment(keysignPayload.memo ?? ''),
|
|
25
23
|
mode,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jetton.js","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/ton/jetton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"jetton.js","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/ton/jetton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAA;AAElE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAA;AAC5E,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAA;AAG7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAS1D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAClC,cAAc,EACd,UAAU,EACV,aAAa,EACb,mBAAmB,GACM,EAAoC,EAAE;IAC/D,MAAM,IAAI,GAAG,cAAc,CAAC,cAAc,CAAC,CAAA;IAE3C,MAAM,kBAAkB,GAAG,UAAU,CAAC,mBAAmB,CAAC,cAAc,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;IAE/G,MAAM,aAAa,GAAG,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IAEnD,MAAM,cAAc,GAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC;QACnE,YAAY,EAAE,gBAAgB,CAAC,eAAe,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC,CAAC;QACjF,OAAO,EAAE,kBAAkB;QAC3B,eAAe,EAAE,IAAI,CAAC,OAAO;QAC7B,aAAa,EAAE,gBAAgB,CAAC,aAAa,CAAC;KAC/C,CAAC,CAAA;IAEF,MAAM,IAAI,GACR,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,mBAAmB,GAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,0BAA0B,CAAA;IAEpH,OAAO,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC7C,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,gBAAgB,CAAC,SAAS,CAAC,YAAY,CAAC;QAChD,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE,aAAa,CAAC,cAAc,CAAC,IAAI,IAAI,EAAE,CAAC;QACjD,IAAI;QACJ,cAAc;KACf,CAAC,CAAA;AACJ,CAAC,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
1
2
|
import { KeysignPayload } from '@vultisig/core-mpc/types/vultisig/keysign/v1/keysign_message_pb';
|
|
2
3
|
import { TW } from '@trustwallet/wallet-core';
|
|
3
4
|
type BuildNativeTonTransferFromMessageInput = {
|
|
@@ -14,6 +15,7 @@ type BuildNativeTonTransferInput = {
|
|
|
14
15
|
};
|
|
15
16
|
export declare const toSafeComment: (payload: string) => string;
|
|
16
17
|
export declare const validateTonComment: (memo: string) => void;
|
|
18
|
+
export declare const tonAmountToBytes: (amount: string | bigint) => Buffer;
|
|
17
19
|
export declare const buildNativeTonTransfer: ({ keysignPayload, bounceable, sendMaxAmount, }: BuildNativeTonTransferInput) => TW.TheOpenNetwork.Proto.Transfer;
|
|
18
20
|
export declare const buildNativeTonTransferFromMessage: ({ to, amount, payload, stateInit, bounceable, }: BuildNativeTonTransferFromMessageInput) => TW.TheOpenNetwork.Proto.Transfer;
|
|
19
21
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/ton/native.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/ton/native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,iEAAiE,CAAA;AAEhG,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAA;AAE7C,KAAK,sCAAsC,GAAG;IAC5C,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,KAAK,2BAA2B,GAAG;IACjC,cAAc,EAAE,cAAc,CAAA;IAC9B,UAAU,EAAE,OAAO,CAAA;IACnB,aAAa,EAAE,OAAO,CAAA;CACvB,CAAA;AAOD,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,MAM/C,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,IAKjD,CAAA;AAMD,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,GAAG,MAAM,KAAG,MAuB1D,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,gDAIpC,2BAA2B,KAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,QAgBxD,CAAA;AAED,eAAO,MAAM,iCAAiC,GAAI,iDAM/C,sCAAsC,KAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,QAanE,CAAA"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Buffer } from 'buffer';
|
|
2
2
|
import { numberToEvenHex } from '@vultisig/lib-utils/hex/numberToHex';
|
|
3
3
|
import { TW } from '@trustwallet/wallet-core';
|
|
4
|
-
import Long from 'long';
|
|
5
4
|
/** TON cell limit is 1023 bits; comment uses ~32 bits opcode + text. Max ~123 bytes. */
|
|
6
5
|
const tonCommentMaxBytes = 123;
|
|
7
6
|
const tonCommentTooLongError = `TON memo exceeds ${tonCommentMaxBytes} bytes and would be truncated; reject oversized memos upstream`;
|
|
@@ -18,15 +17,37 @@ export const validateTonComment = (memo) => {
|
|
|
18
17
|
throw new Error(`TON memo must be at most ${tonCommentMaxBytes} bytes (got ${bytes.length})`);
|
|
19
18
|
}
|
|
20
19
|
};
|
|
20
|
+
const tonUnsignedDecimalRegex = /^\d+$/;
|
|
21
|
+
const tonMaxAmount = (1n << 120n) - 1n;
|
|
22
|
+
const tonMaxAmountDecimal = tonMaxAmount.toString();
|
|
23
|
+
export const tonAmountToBytes = (amount) => {
|
|
24
|
+
if (typeof amount === 'string' && !tonUnsignedDecimalRegex.test(amount)) {
|
|
25
|
+
throw new Error('TON amount must be a non-negative integer');
|
|
26
|
+
}
|
|
27
|
+
const normalizedAmount = typeof amount === 'string' ? amount.replace(/^0+(?=\d)/, '') : amount;
|
|
28
|
+
if (typeof normalizedAmount === 'string' &&
|
|
29
|
+
(normalizedAmount.length > tonMaxAmountDecimal.length ||
|
|
30
|
+
(normalizedAmount.length === tonMaxAmountDecimal.length && normalizedAmount > tonMaxAmountDecimal))) {
|
|
31
|
+
throw new Error('TON amount exceeds the VarUInteger 16 maximum');
|
|
32
|
+
}
|
|
33
|
+
const value = typeof normalizedAmount === 'bigint' ? normalizedAmount : BigInt(normalizedAmount);
|
|
34
|
+
if (value < 0n) {
|
|
35
|
+
throw new Error('TON amount must be a non-negative integer');
|
|
36
|
+
}
|
|
37
|
+
if (value > tonMaxAmount) {
|
|
38
|
+
throw new Error('TON amount exceeds the VarUInteger 16 maximum');
|
|
39
|
+
}
|
|
40
|
+
return Buffer.from(numberToEvenHex(value), 'hex');
|
|
41
|
+
};
|
|
21
42
|
export const buildNativeTonTransfer = ({ keysignPayload, bounceable, sendMaxAmount, }) => {
|
|
22
43
|
const mode = (sendMaxAmount
|
|
23
44
|
? TW.TheOpenNetwork.Proto.SendMode.ATTACH_ALL_CONTRACT_BALANCE
|
|
24
45
|
: TW.TheOpenNetwork.Proto.SendMode.PAY_FEES_SEPARATELY) |
|
|
25
46
|
TW.TheOpenNetwork.Proto.SendMode.IGNORE_ACTION_PHASE_ERRORS;
|
|
26
|
-
const amount = sendMaxAmount ?
|
|
47
|
+
const amount = sendMaxAmount ? 0n : keysignPayload.toAmount;
|
|
27
48
|
return TW.TheOpenNetwork.Proto.Transfer.create({
|
|
28
49
|
dest: keysignPayload.toAddress,
|
|
29
|
-
amount:
|
|
50
|
+
amount: tonAmountToBytes(amount),
|
|
30
51
|
bounceable,
|
|
31
52
|
comment: toSafeComment(keysignPayload.memo || ''),
|
|
32
53
|
mode,
|
|
@@ -36,7 +57,7 @@ export const buildNativeTonTransferFromMessage = ({ to, amount, payload = '', st
|
|
|
36
57
|
const mode = TW.TheOpenNetwork.Proto.SendMode.PAY_FEES_SEPARATELY | TW.TheOpenNetwork.Proto.SendMode.IGNORE_ACTION_PHASE_ERRORS;
|
|
37
58
|
return TW.TheOpenNetwork.Proto.Transfer.create({
|
|
38
59
|
dest: to,
|
|
39
|
-
amount:
|
|
60
|
+
amount: tonAmountToBytes(amount),
|
|
40
61
|
bounceable,
|
|
41
62
|
comment: '',
|
|
42
63
|
customPayload: payload || undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/ton/native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA;AACrE,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../../../../../../../packages/core/mpc/keysign/signingInputs/resolvers/ton/native.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SuiCoin } from '../types/vultisig/keysign/v1/blockchain_specific_pb.js';
|
|
2
|
+
export declare const suiNativeCoinType = "0x2::sui::SUI";
|
|
3
|
+
export declare const maxSuiInputCoinObjects = 255;
|
|
4
|
+
export declare const suiGasCandidateObjectCount = 5;
|
|
5
|
+
export declare const normalizeSuiCoinType: (coinType: string) => string;
|
|
6
|
+
export declare const isSameSuiCoinType: (lhs: string, rhs: string) => boolean;
|
|
7
|
+
export declare const isNativeSuiCoin: ({ coinType }: Pick<SuiCoin, "coinType">) => boolean;
|
|
8
|
+
export declare const getSuiCoinBalance: ({ balance }: Pick<SuiCoin, "balance">) => bigint;
|
|
9
|
+
export declare const selectSuiInputCoins: (coins: readonly SuiCoin[], target: bigint, maxObjects?: number) => SuiCoin[];
|
|
10
|
+
export declare const selectSuiGasObject: (coins: readonly SuiCoin[], gasBudget: bigint) => SuiCoin | undefined;
|
|
11
|
+
type SelectSuiPayloadCoinsInput = {
|
|
12
|
+
coins: readonly SuiCoin[];
|
|
13
|
+
isNativeToken: boolean;
|
|
14
|
+
coinType?: string;
|
|
15
|
+
amount: bigint;
|
|
16
|
+
gasBudget: bigint;
|
|
17
|
+
};
|
|
18
|
+
export declare const selectSuiPayloadCoins: ({ coins, isNativeToken, coinType, amount, gasBudget, }: SelectSuiPayloadCoinsInput) => SuiCoin[];
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=suiCoinSelection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suiCoinSelection.d.ts","sourceRoot":"","sources":["../../../../../packages/core/mpc/keysign/suiCoinSelection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qDAAqD,CAAA;AAE7E,eAAO,MAAM,iBAAiB,kBAAkB,CAAA;AAEhD,eAAO,MAAM,sBAAsB,MAAM,CAAA;AACzC,eAAO,MAAM,0BAA0B,IAAI,CAAA;AAS3C,eAAO,MAAM,oBAAoB,GAAI,UAAU,MAAM,KAAG,MAOvD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,OACJ,CAAA;AAEzD,eAAO,MAAM,eAAe,GAAI,cAAc,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,KAAG,OAC1B,CAAA;AAEhD,eAAO,MAAM,iBAAiB,GAAI,aAAa,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,KAAG,MAMzE,CAAA;AAED,eAAO,MAAM,mBAAmB,GAC9B,OAAO,SAAS,OAAO,EAAE,EACzB,QAAQ,MAAM,EACd,mBAAmC,KAClC,OAAO,EA0BT,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,OAAO,SAAS,OAAO,EAAE,EAAE,WAAW,MAAM,KAAG,OAAO,GAAG,SAkB3F,CAAA;AAED,KAAK,0BAA0B,GAAG;IAChC,KAAK,EAAE,SAAS,OAAO,EAAE,CAAA;IACzB,aAAa,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,wDAMnC,0BAA0B,KAAG,OAAO,EAuBtC,CAAA"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export const suiNativeCoinType = '0x2::sui::SUI';
|
|
2
|
+
export const maxSuiInputCoinObjects = 255;
|
|
3
|
+
export const suiGasCandidateObjectCount = 5;
|
|
4
|
+
const normalizeSuiAddress = (address) => {
|
|
5
|
+
const lowered = address.toLowerCase();
|
|
6
|
+
const hex = lowered.startsWith('0x') ? lowered.slice(2) : lowered;
|
|
7
|
+
const trimmed = hex.replace(/^0+/, '');
|
|
8
|
+
return `0x${trimmed || '0'}`;
|
|
9
|
+
};
|
|
10
|
+
export const normalizeSuiCoinType = (coinType) => {
|
|
11
|
+
const addressEnd = coinType.indexOf('::');
|
|
12
|
+
if (addressEnd < 0) {
|
|
13
|
+
return normalizeSuiAddress(coinType);
|
|
14
|
+
}
|
|
15
|
+
return `${normalizeSuiAddress(coinType.slice(0, addressEnd))}${coinType.slice(addressEnd)}`;
|
|
16
|
+
};
|
|
17
|
+
export const isSameSuiCoinType = (lhs, rhs) => normalizeSuiCoinType(lhs) === normalizeSuiCoinType(rhs);
|
|
18
|
+
export const isNativeSuiCoin = ({ coinType }) => isSameSuiCoinType(coinType, suiNativeCoinType);
|
|
19
|
+
export const getSuiCoinBalance = ({ balance }) => {
|
|
20
|
+
try {
|
|
21
|
+
return BigInt(balance || '0');
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return 0n;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
export const selectSuiInputCoins = (coins, target, maxObjects = maxSuiInputCoinObjects) => {
|
|
28
|
+
const sorted = [...coins].sort((lhs, rhs) => {
|
|
29
|
+
const lhsBalance = getSuiCoinBalance(lhs);
|
|
30
|
+
const rhsBalance = getSuiCoinBalance(rhs);
|
|
31
|
+
if (lhsBalance !== rhsBalance) {
|
|
32
|
+
return lhsBalance > rhsBalance ? -1 : 1;
|
|
33
|
+
}
|
|
34
|
+
return lhs.coinObjectId.localeCompare(rhs.coinObjectId);
|
|
35
|
+
});
|
|
36
|
+
const selected = [];
|
|
37
|
+
let accumulated = 0n;
|
|
38
|
+
for (const coin of sorted) {
|
|
39
|
+
if (selected.length > 0 && accumulated >= target)
|
|
40
|
+
break;
|
|
41
|
+
if (selected.length >= maxObjects)
|
|
42
|
+
break;
|
|
43
|
+
selected.push(coin);
|
|
44
|
+
accumulated += getSuiCoinBalance(coin);
|
|
45
|
+
}
|
|
46
|
+
if (accumulated < target) {
|
|
47
|
+
throw new Error(`Insufficient Sui coin balance to cover ${target.toString()}`);
|
|
48
|
+
}
|
|
49
|
+
return selected;
|
|
50
|
+
};
|
|
51
|
+
export const selectSuiGasObject = (coins, gasBudget) => {
|
|
52
|
+
const nativeCoins = coins.filter(isNativeSuiCoin);
|
|
53
|
+
if (nativeCoins.length === 0)
|
|
54
|
+
return undefined;
|
|
55
|
+
const covering = nativeCoins.filter(coin => getSuiCoinBalance(coin) >= gasBudget);
|
|
56
|
+
if (covering.length > 0) {
|
|
57
|
+
return covering.sort((lhs, rhs) => {
|
|
58
|
+
const lhsBalance = getSuiCoinBalance(lhs);
|
|
59
|
+
const rhsBalance = getSuiCoinBalance(rhs);
|
|
60
|
+
if (lhsBalance !== rhsBalance) {
|
|
61
|
+
return lhsBalance < rhsBalance ? -1 : 1;
|
|
62
|
+
}
|
|
63
|
+
return lhs.coinObjectId.localeCompare(rhs.coinObjectId);
|
|
64
|
+
})[0];
|
|
65
|
+
}
|
|
66
|
+
throw new Error(`Insufficient SUI balance to cover gas budget ${gasBudget.toString()}`);
|
|
67
|
+
};
|
|
68
|
+
export const selectSuiPayloadCoins = ({ coins, isNativeToken, coinType, amount, gasBudget, }) => {
|
|
69
|
+
const nativeCoins = coins.filter(isNativeSuiCoin);
|
|
70
|
+
if (isNativeToken) {
|
|
71
|
+
return selectSuiInputCoins(nativeCoins, amount + gasBudget);
|
|
72
|
+
}
|
|
73
|
+
const tokenType = coinType || suiNativeCoinType;
|
|
74
|
+
const tokenCoins = coins.filter(coin => isSameSuiCoinType(coin.coinType, tokenType));
|
|
75
|
+
const selectedTokens = selectSuiInputCoins(tokenCoins, amount);
|
|
76
|
+
const gasCandidates = [...nativeCoins]
|
|
77
|
+
.sort((lhs, rhs) => {
|
|
78
|
+
const lhsBalance = getSuiCoinBalance(lhs);
|
|
79
|
+
const rhsBalance = getSuiCoinBalance(rhs);
|
|
80
|
+
if (lhsBalance !== rhsBalance) {
|
|
81
|
+
return lhsBalance > rhsBalance ? -1 : 1;
|
|
82
|
+
}
|
|
83
|
+
return lhs.coinObjectId.localeCompare(rhs.coinObjectId);
|
|
84
|
+
})
|
|
85
|
+
.slice(0, suiGasCandidateObjectCount);
|
|
86
|
+
return [...selectedTokens, ...gasCandidates];
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=suiCoinSelection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suiCoinSelection.js","sourceRoot":"","sources":["../../../../../packages/core/mpc/keysign/suiCoinSelection.ts"],"names":[],"mappings":"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"}
|