@vultisig/core-chain 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/chains/cardano/cip30/buildCardanoValue.d.ts +18 -0
- package/dist/chains/cardano/cip30/buildCardanoValue.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/buildCardanoValue.js +72 -0
- package/dist/chains/cardano/cip30/buildCardanoValue.js.map +1 -0
- package/dist/chains/cardano/cip30/buildCardanoWitnessSet.d.ts +10 -0
- package/dist/chains/cardano/cip30/buildCardanoWitnessSet.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/buildCardanoWitnessSet.js +15 -0
- package/dist/chains/cardano/cip30/buildCardanoWitnessSet.js.map +1 -0
- package/dist/chains/cardano/cip30/buildCoseStructures.d.ts +45 -0
- package/dist/chains/cardano/cip30/buildCoseStructures.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/buildCoseStructures.js +70 -0
- package/dist/chains/cardano/cip30/buildCoseStructures.js.map +1 -0
- package/dist/chains/cardano/cip30/cardanoAddressBytes.d.ts +6 -0
- package/dist/chains/cardano/cip30/cardanoAddressBytes.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/cardanoAddressBytes.js +12 -0
- package/dist/chains/cardano/cip30/cardanoAddressBytes.js.map +1 -0
- package/dist/chains/cardano/cip30/cardanoCborPrimitives.d.ts +53 -0
- package/dist/chains/cardano/cip30/cardanoCborPrimitives.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/cardanoCborPrimitives.js +91 -0
- package/dist/chains/cardano/cip30/cardanoCborPrimitives.js.map +1 -0
- package/dist/chains/cardano/cip30/cardanoTxBodyHash.d.ts +6 -0
- package/dist/chains/cardano/cip30/cardanoTxBodyHash.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/cardanoTxBodyHash.js +55 -0
- package/dist/chains/cardano/cip30/cardanoTxBodyHash.js.map +1 -0
- package/dist/chains/cardano/cip30/cborEncoder.d.ts +11 -0
- package/dist/chains/cardano/cip30/cborEncoder.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/cborEncoder.js +14 -0
- package/dist/chains/cardano/cip30/cborEncoder.js.map +1 -0
- package/dist/chains/cardano/cip30/cborSkip.d.ts +13 -0
- package/dist/chains/cardano/cip30/cborSkip.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/cborSkip.js +108 -0
- package/dist/chains/cardano/cip30/cborSkip.js.map +1 -0
- package/dist/chains/cardano/cip30/decodeCardanoAmountValue.d.ts +16 -0
- package/dist/chains/cardano/cip30/decodeCardanoAmountValue.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/decodeCardanoAmountValue.js +72 -0
- package/dist/chains/cardano/cip30/decodeCardanoAmountValue.js.map +1 -0
- package/dist/chains/cardano/cip30/encodeCardanoUnspentOutput.d.ts +16 -0
- package/dist/chains/cardano/cip30/encodeCardanoUnspentOutput.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/encodeCardanoUnspentOutput.js +23 -0
- package/dist/chains/cardano/cip30/encodeCardanoUnspentOutput.js.map +1 -0
- package/dist/chains/cardano/cip30/encodeCardanoValue.d.ts +4 -0
- package/dist/chains/cardano/cip30/encodeCardanoValue.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/encodeCardanoValue.js +5 -0
- package/dist/chains/cardano/cip30/encodeCardanoValue.js.map +1 -0
- package/dist/chains/cardano/cip30/selectCardanoUtxosByLovelace.d.ts +24 -0
- package/dist/chains/cardano/cip30/selectCardanoUtxosByLovelace.d.ts.map +1 -0
- package/dist/chains/cardano/cip30/selectCardanoUtxosByLovelace.js +23 -0
- package/dist/chains/cardano/cip30/selectCardanoUtxosByLovelace.js.map +1 -0
- package/dist/chains/cardano/submit/submitCardanoCbor.d.ts +18 -0
- package/dist/chains/cardano/submit/submitCardanoCbor.d.ts.map +1 -0
- package/dist/chains/cardano/submit/submitCardanoCbor.js +71 -0
- package/dist/chains/cardano/submit/submitCardanoCbor.js.map +1 -0
- package/dist/tx/broadcast/resolvers/cardano.d.ts.map +1 -1
- package/dist/tx/broadcast/resolvers/cardano.js +11 -63
- package/dist/tx/broadcast/resolvers/cardano.js.map +1 -1
- package/package.json +66 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walk a CBOR data item starting at `offset` and return the offset
|
|
3
|
+
* immediately after the item ends. This allows extracting raw byte
|
|
4
|
+
* ranges from CBOR without re-encoding.
|
|
5
|
+
*
|
|
6
|
+
* Supports: unsigned/negative ints, byte/text strings, arrays, maps, tags,
|
|
7
|
+
* and simple values (true/false/null). Does NOT support indefinite-length.
|
|
8
|
+
*
|
|
9
|
+
* Every read is bounds-checked so a truncated / malformed CBOR input fails
|
|
10
|
+
* fast with a descriptive error instead of silently returning bogus offsets.
|
|
11
|
+
*/
|
|
12
|
+
export const cborSkip = (data, offset) => {
|
|
13
|
+
if (!Number.isInteger(offset) || offset < 0 || offset >= data.length) {
|
|
14
|
+
throw new Error(`cborSkip: offset ${offset} is out of bounds (data length ${data.length})`);
|
|
15
|
+
}
|
|
16
|
+
const initial = data[offset];
|
|
17
|
+
const majorType = initial >> 5;
|
|
18
|
+
const additional = initial & 0x1f;
|
|
19
|
+
const { value, nextOffset } = readArgument(data, offset, additional);
|
|
20
|
+
// Major type 0/1: unsigned/negative integer — head only
|
|
21
|
+
if (majorType <= 1)
|
|
22
|
+
return nextOffset;
|
|
23
|
+
// Major type 2/3: byte/text string — head + N bytes
|
|
24
|
+
if (majorType <= 3) {
|
|
25
|
+
const end = nextOffset + Number(value);
|
|
26
|
+
if (end > data.length) {
|
|
27
|
+
throw new Error(`cborSkip: truncated string at offset ${offset} (need ${Number(value)} bytes, have ${data.length - nextOffset})`);
|
|
28
|
+
}
|
|
29
|
+
return end;
|
|
30
|
+
}
|
|
31
|
+
// Major type 4: array — head + N items
|
|
32
|
+
if (majorType === 4) {
|
|
33
|
+
let pos = nextOffset;
|
|
34
|
+
for (let i = 0; i < Number(value); i++) {
|
|
35
|
+
pos = cborSkip(data, pos);
|
|
36
|
+
}
|
|
37
|
+
return pos;
|
|
38
|
+
}
|
|
39
|
+
// Major type 5: map — head + N key-value pairs
|
|
40
|
+
if (majorType === 5) {
|
|
41
|
+
let pos = nextOffset;
|
|
42
|
+
for (let i = 0; i < Number(value); i++) {
|
|
43
|
+
pos = cborSkip(data, pos); // key
|
|
44
|
+
pos = cborSkip(data, pos); // value
|
|
45
|
+
}
|
|
46
|
+
return pos;
|
|
47
|
+
}
|
|
48
|
+
// Major type 6: tag — head + 1 nested item
|
|
49
|
+
if (majorType === 6)
|
|
50
|
+
return cborSkip(data, nextOffset);
|
|
51
|
+
// Major type 7: simple values / floats
|
|
52
|
+
if (additional <= 23)
|
|
53
|
+
return nextOffset; // simple value in head
|
|
54
|
+
if (additional === 24)
|
|
55
|
+
return nextOffset; // 1-byte simple
|
|
56
|
+
if (additional === 25)
|
|
57
|
+
return nextOffset; // float16 (2 bytes in arg)
|
|
58
|
+
if (additional === 26)
|
|
59
|
+
return nextOffset; // float32 (4 bytes in arg)
|
|
60
|
+
if (additional === 27)
|
|
61
|
+
return nextOffset; // float64 (8 bytes in arg)
|
|
62
|
+
throw new Error(`Unsupported CBOR item at offset ${offset}: initial byte 0x${initial.toString(16)}`);
|
|
63
|
+
};
|
|
64
|
+
/** Read the argument value and return the offset after the argument. */
|
|
65
|
+
const readArgument = (data, offset, additional) => {
|
|
66
|
+
const ensureBytes = (needed) => {
|
|
67
|
+
const end = offset + 1 + needed;
|
|
68
|
+
if (end > data.length) {
|
|
69
|
+
throw new Error(`cborSkip/readArgument: truncated CBOR head at offset ${offset} (need ${needed} argument bytes, have ${data.length - offset - 1})`);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
if (additional < 24)
|
|
73
|
+
return { value: BigInt(additional), nextOffset: offset + 1 };
|
|
74
|
+
if (additional === 24) {
|
|
75
|
+
ensureBytes(1);
|
|
76
|
+
return { value: BigInt(data[offset + 1]), nextOffset: offset + 2 };
|
|
77
|
+
}
|
|
78
|
+
if (additional === 25) {
|
|
79
|
+
ensureBytes(2);
|
|
80
|
+
const v = (data[offset + 1] << 8) | data[offset + 2];
|
|
81
|
+
return { value: BigInt(v), nextOffset: offset + 3 };
|
|
82
|
+
}
|
|
83
|
+
if (additional === 26) {
|
|
84
|
+
ensureBytes(4);
|
|
85
|
+
const v = (data[offset + 1] << 24) |
|
|
86
|
+
(data[offset + 2] << 16) |
|
|
87
|
+
(data[offset + 3] << 8) |
|
|
88
|
+
data[offset + 4];
|
|
89
|
+
return { value: BigInt(v >>> 0), nextOffset: offset + 5 };
|
|
90
|
+
}
|
|
91
|
+
if (additional === 27) {
|
|
92
|
+
ensureBytes(8);
|
|
93
|
+
const hi = (data[offset + 1] << 24) |
|
|
94
|
+
(data[offset + 2] << 16) |
|
|
95
|
+
(data[offset + 3] << 8) |
|
|
96
|
+
data[offset + 4];
|
|
97
|
+
const lo = (data[offset + 5] << 24) |
|
|
98
|
+
(data[offset + 6] << 16) |
|
|
99
|
+
(data[offset + 7] << 8) |
|
|
100
|
+
data[offset + 8];
|
|
101
|
+
return {
|
|
102
|
+
value: (BigInt(hi >>> 0) << 32n) | BigInt(lo >>> 0),
|
|
103
|
+
nextOffset: offset + 9,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
throw new Error(`Unsupported CBOR additional info ${additional}`);
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=cborSkip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cborSkip.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cardano/cip30/cborSkip.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decoded shape of a CIP-30 `amount` argument:
|
|
3
|
+
*
|
|
4
|
+
* value = coin / [coin, multiasset<uint>]
|
|
5
|
+
*
|
|
6
|
+
* We surface `hasAssets` as a boolean rather than a full multiasset tree
|
|
7
|
+
* because the main consumer (`getUtxos` coin selection) only selects by
|
|
8
|
+
* lovelace and falls back to a conservative "return all" when the request
|
|
9
|
+
* also has native-token requirements.
|
|
10
|
+
*/
|
|
11
|
+
export type CardanoValueRequirement = {
|
|
12
|
+
lovelace: bigint;
|
|
13
|
+
hasAssets: boolean;
|
|
14
|
+
};
|
|
15
|
+
export declare const decodeCardanoAmountValue: (amountHex: string) => CardanoValueRequirement | null;
|
|
16
|
+
//# sourceMappingURL=decodeCardanoAmountValue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decodeCardanoAmountValue.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cardano/cip30/decodeCardanoAmountValue.ts"],"names":[],"mappings":"AAMA;;;;;;;;;GASG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,OAAO,CAAA;CACnB,CAAA;AAoED,eAAO,MAAM,wBAAwB,GACnC,WAAW,MAAM,KAChB,uBAAuB,GAAG,IAI5B,CAAA"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { stripHexPrefix } from '@vultisig/lib-utils/hex/stripHexPrefix';
|
|
2
|
+
import { attempt } from '@vultisig/lib-utils/attempt';
|
|
3
|
+
import { cardanoCborEncoder } from './cborEncoder.js';
|
|
4
|
+
const hexPattern = /^[0-9a-fA-F]*$/;
|
|
5
|
+
/** Cardano coin is always a non-negative uint — reject anything else. */
|
|
6
|
+
const toBigInt = (value) => {
|
|
7
|
+
if (typeof value === 'bigint')
|
|
8
|
+
return value >= 0n ? value : null;
|
|
9
|
+
if (typeof value === 'number' && Number.isInteger(value) && value >= 0) {
|
|
10
|
+
return BigInt(value);
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* A valid multiasset is a CBOR map:
|
|
16
|
+
*
|
|
17
|
+
* multiasset<a> = { * policy_id => { * asset_name => a } }
|
|
18
|
+
*
|
|
19
|
+
* cbor-x decodes this as a `Map` (because we set `mapsAsObjects: false`), but
|
|
20
|
+
* we accept a plain non-array object too for robustness against inputs that
|
|
21
|
+
* went through a re-encode pass elsewhere. Arrays and scalars are rejected.
|
|
22
|
+
*/
|
|
23
|
+
const isMultiassetShape = (value) => value instanceof Map ||
|
|
24
|
+
(typeof value === 'object' && value !== null && !Array.isArray(value));
|
|
25
|
+
const multiassetHasEntries = (value) => {
|
|
26
|
+
if (value instanceof Map)
|
|
27
|
+
return value.size > 0;
|
|
28
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
29
|
+
return Object.keys(value).length > 0;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Decode a hex-encoded CBOR `value` (per CIP-30 `getUtxos(amount)`).
|
|
35
|
+
*
|
|
36
|
+
* Returns `null` for inputs that fail to decode or don't match the
|
|
37
|
+
* `coin / [coin, multiasset]` shape — callers should treat a null result as
|
|
38
|
+
* "no usable filter" and fall back to returning all UTXOs.
|
|
39
|
+
*/
|
|
40
|
+
const tryDecode = (amountHex) => {
|
|
41
|
+
const stripped = stripHexPrefix(amountHex);
|
|
42
|
+
// Buffer.from('...', 'hex') silently truncates at the first non-hex byte,
|
|
43
|
+
// which would let `0xgg` or odd-length inputs squeak past as valid-looking
|
|
44
|
+
// (but wrong) CBOR. Validate up front.
|
|
45
|
+
if (stripped.length === 0 || stripped.length % 2 !== 0 || !hexPattern.test(stripped)) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const bytes = Uint8Array.from(Buffer.from(stripped, 'hex'));
|
|
49
|
+
if (bytes.length === 0)
|
|
50
|
+
return null;
|
|
51
|
+
const decoded = cardanoCborEncoder.decode(bytes);
|
|
52
|
+
if (Array.isArray(decoded) && decoded.length === 2) {
|
|
53
|
+
const lovelace = toBigInt(decoded[0]);
|
|
54
|
+
if (lovelace === null)
|
|
55
|
+
return null;
|
|
56
|
+
const ma = decoded[1];
|
|
57
|
+
if (!isMultiassetShape(ma))
|
|
58
|
+
return null;
|
|
59
|
+
return { lovelace, hasAssets: multiassetHasEntries(ma) };
|
|
60
|
+
}
|
|
61
|
+
const lovelace = toBigInt(decoded);
|
|
62
|
+
if (lovelace === null)
|
|
63
|
+
return null;
|
|
64
|
+
return { lovelace, hasAssets: false };
|
|
65
|
+
};
|
|
66
|
+
export const decodeCardanoAmountValue = (amountHex) => {
|
|
67
|
+
const result = attempt(() => tryDecode(amountHex));
|
|
68
|
+
if ('error' in result)
|
|
69
|
+
return null;
|
|
70
|
+
return result.data ?? null;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=decodeCardanoAmountValue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decodeCardanoAmountValue.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cardano/cip30/decodeCardanoAmountValue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CardanoExtendedUtxo } from '../utxo/getCardanoExtendedUtxos.js';
|
|
2
|
+
type Input = {
|
|
3
|
+
utxo: CardanoExtendedUtxo;
|
|
4
|
+
addressBytes: Uint8Array;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* CBOR-encode a CIP-30 `transaction_unspent_output = [input, output]`:
|
|
8
|
+
*
|
|
9
|
+
* transaction_input = [ tx_hash: bytes .size 32, index: uint ]
|
|
10
|
+
* transaction_output = [ address: bytes, amount: value ]
|
|
11
|
+
*
|
|
12
|
+
* `address_bytes` should already be the raw address bytes (see `cardanoAddressBytes`).
|
|
13
|
+
*/
|
|
14
|
+
export declare const encodeCardanoUnspentOutput: ({ utxo, addressBytes, }: Input) => Uint8Array;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=encodeCardanoUnspentOutput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encodeCardanoUnspentOutput.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cardano/cip30/encodeCardanoUnspentOutput.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AAOrE,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,mBAAmB,CAAA;IACzB,YAAY,EAAE,UAAU,CAAA;CACzB,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,GAAI,yBAGxC,KAAK,KAAG,UAWV,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { stripHexPrefix } from '@vultisig/lib-utils/hex/stripHexPrefix';
|
|
2
|
+
import { buildCardanoValue } from './buildCardanoValue.js';
|
|
3
|
+
import { cardanoCborEncoder } from './cborEncoder.js';
|
|
4
|
+
const hexToBytes = (hex) => Uint8Array.from(Buffer.from(stripHexPrefix(hex), 'hex'));
|
|
5
|
+
/**
|
|
6
|
+
* CBOR-encode a CIP-30 `transaction_unspent_output = [input, output]`:
|
|
7
|
+
*
|
|
8
|
+
* transaction_input = [ tx_hash: bytes .size 32, index: uint ]
|
|
9
|
+
* transaction_output = [ address: bytes, amount: value ]
|
|
10
|
+
*
|
|
11
|
+
* `address_bytes` should already be the raw address bytes (see `cardanoAddressBytes`).
|
|
12
|
+
*/
|
|
13
|
+
export const encodeCardanoUnspentOutput = ({ utxo, addressBytes, }) => {
|
|
14
|
+
const txHashBytes = hexToBytes(utxo.hash);
|
|
15
|
+
if (txHashBytes.length !== 32) {
|
|
16
|
+
throw new Error(`encodeCardanoUnspentOutput: tx_hash must be 32 bytes, got ${txHashBytes.length} (hash=${JSON.stringify(utxo.hash)})`);
|
|
17
|
+
}
|
|
18
|
+
return cardanoCborEncoder.encode([
|
|
19
|
+
[txHashBytes, utxo.index],
|
|
20
|
+
[addressBytes, buildCardanoValue(utxo.amount, utxo.assets)],
|
|
21
|
+
]);
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=encodeCardanoUnspentOutput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encodeCardanoUnspentOutput.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cardano/cip30/encodeCardanoUnspentOutput.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAA;AAGvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,MAAM,UAAU,GAAG,CAAC,GAAW,EAAc,EAAE,CAC7C,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;AAO1D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,EACzC,IAAI,EACJ,YAAY,GACN,EAAc,EAAE;IACtB,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzC,IAAI,WAAW,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,6DAA6D,WAAW,CAAC,MAAM,UAAU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACtH,CAAA;IACH,CAAC;IACD,OAAO,kBAAkB,CAAC,MAAM,CAAC;QAC/B,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC;QACzB,CAAC,YAAY,EAAE,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;KAC5D,CAAC,CAAA;AACJ,CAAC,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CardanoNativeAsset } from './buildCardanoValue.js';
|
|
2
|
+
/** CBOR-encode a Cardano `value` — the shape returned by `getBalance()` under CIP-30. */
|
|
3
|
+
export declare const encodeCardanoValue: (lovelace: bigint, assets: readonly CardanoNativeAsset[]) => Uint8Array;
|
|
4
|
+
//# sourceMappingURL=encodeCardanoValue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encodeCardanoValue.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cardano/cip30/encodeCardanoValue.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,kBAAkB,EACnB,MAAM,qBAAqB,CAAA;AAG5B,yFAAyF;AACzF,eAAO,MAAM,kBAAkB,GAC7B,UAAU,MAAM,EAChB,QAAQ,SAAS,kBAAkB,EAAE,KACpC,UAC6D,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { buildCardanoValue, } from './buildCardanoValue.js';
|
|
2
|
+
import { cardanoCborEncoder } from './cborEncoder.js';
|
|
3
|
+
/** CBOR-encode a Cardano `value` — the shape returned by `getBalance()` under CIP-30. */
|
|
4
|
+
export const encodeCardanoValue = (lovelace, assets) => cardanoCborEncoder.encode(buildCardanoValue(lovelace, assets));
|
|
5
|
+
//# sourceMappingURL=encodeCardanoValue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encodeCardanoValue.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cardano/cip30/encodeCardanoValue.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,GAElB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,yFAAyF;AACzF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,QAAgB,EAChB,MAAqC,EACzB,EAAE,CACd,kBAAkB,CAAC,MAAM,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal UTXO shape required by lovelace coin selection. Matches
|
|
3
|
+
* `CardanoExtendedUtxo` but is structurally typed so callers can pass any
|
|
4
|
+
* row with an `amount: bigint`.
|
|
5
|
+
*/
|
|
6
|
+
export type CardanoCoinSelectionUtxo = {
|
|
7
|
+
amount: bigint;
|
|
8
|
+
};
|
|
9
|
+
export type SelectCardanoUtxosByLovelaceInput<T extends CardanoCoinSelectionUtxo> = {
|
|
10
|
+
utxos: readonly T[];
|
|
11
|
+
targetLovelace: bigint;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Greedy largest-first coin selection by lovelace.
|
|
15
|
+
*
|
|
16
|
+
* Used by CIP-30 `getUtxos(amount)` to return a minimal covering set. The
|
|
17
|
+
* wallet is free to return a superset (the spec explicitly allows it), but
|
|
18
|
+
* picking largest-first keeps the returned set small, which reduces the
|
|
19
|
+
* CBOR payload size and the dApp's downstream selection work.
|
|
20
|
+
*
|
|
21
|
+
* Returns `null` when even the full set is insufficient to meet the target.
|
|
22
|
+
*/
|
|
23
|
+
export declare const selectCardanoUtxosByLovelace: <T extends CardanoCoinSelectionUtxo>({ utxos, targetLovelace, }: SelectCardanoUtxosByLovelaceInput<T>) => T[] | null;
|
|
24
|
+
//# sourceMappingURL=selectCardanoUtxosByLovelace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectCardanoUtxosByLovelace.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cardano/cip30/selectCardanoUtxosByLovelace.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEzD,MAAM,MAAM,iCAAiC,CAAC,CAAC,SAAS,wBAAwB,IAAI;IAClF,KAAK,EAAE,SAAS,CAAC,EAAE,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,SAAS,wBAAwB,EAAE,4BAG9E,iCAAiC,CAAC,CAAC,CAAC,KAAG,CAAC,EAAE,GAAG,IAY/C,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Greedy largest-first coin selection by lovelace.
|
|
3
|
+
*
|
|
4
|
+
* Used by CIP-30 `getUtxos(amount)` to return a minimal covering set. The
|
|
5
|
+
* wallet is free to return a superset (the spec explicitly allows it), but
|
|
6
|
+
* picking largest-first keeps the returned set small, which reduces the
|
|
7
|
+
* CBOR payload size and the dApp's downstream selection work.
|
|
8
|
+
*
|
|
9
|
+
* Returns `null` when even the full set is insufficient to meet the target.
|
|
10
|
+
*/
|
|
11
|
+
export const selectCardanoUtxosByLovelace = ({ utxos, targetLovelace, }) => {
|
|
12
|
+
const sorted = [...utxos].sort((a, b) => a.amount > b.amount ? -1 : a.amount < b.amount ? 1 : 0);
|
|
13
|
+
let total = 0n;
|
|
14
|
+
const picked = [];
|
|
15
|
+
for (const u of sorted) {
|
|
16
|
+
if (total >= targetLovelace)
|
|
17
|
+
break;
|
|
18
|
+
picked.push(u);
|
|
19
|
+
total += u.amount;
|
|
20
|
+
}
|
|
21
|
+
return total >= targetLovelace ? picked : null;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=selectCardanoUtxosByLovelace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectCardanoUtxosByLovelace.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cardano/cip30/selectCardanoUtxosByLovelace.ts"],"names":[],"mappings":"AAYA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAqC,EAC/E,KAAK,EACL,cAAc,GACuB,EAAc,EAAE;IACrD,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACtC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACvD,CAAA;IACD,IAAI,KAAK,GAAG,EAAE,CAAA;IACd,MAAM,MAAM,GAAQ,EAAE,CAAA;IACtB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,KAAK,IAAI,cAAc;YAAE,MAAK;QAClC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACd,KAAK,IAAI,CAAC,CAAC,MAAM,CAAA;IACnB,CAAC;IACD,OAAO,KAAK,IAAI,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;AAChD,CAAC,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Low-level result so callers can branch on already-committed (3117) etc. */
|
|
2
|
+
export type SubmitCardanoCborResult = {
|
|
3
|
+
txHash: string | null;
|
|
4
|
+
errorMessage: string | null;
|
|
5
|
+
/** JSON-RPC error code from the node, when present. */
|
|
6
|
+
rpcErrorCode?: number;
|
|
7
|
+
/** Raw response body, for callers that want to log or pattern match. */
|
|
8
|
+
rawResponse: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Broadcast a hex-encoded Cardano transaction CBOR via the Vultisig Ogmios JSON-RPC proxy.
|
|
12
|
+
*
|
|
13
|
+
* This low-level helper exposes the raw response so higher-level callers can
|
|
14
|
+
* distinguish "already-committed" (`rpcErrorCode === 3117`), mempool conflicts,
|
|
15
|
+
* etc. For the common "submit or throw" shape, use `submitCardanoCborTx`.
|
|
16
|
+
*/
|
|
17
|
+
export declare const submitCardanoCbor: (cborHex: string) => Promise<SubmitCardanoCborResult>;
|
|
18
|
+
//# sourceMappingURL=submitCardanoCbor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submitCardanoCbor.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cardano/submit/submitCardanoCbor.ts"],"names":[],"mappings":"AAkBA,8EAA8E;AAC9E,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,KACd,OAAO,CAAC,uBAAuB,CAmEjC,CAAA"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { rootApiUrl } from '@vultisig/core-config';
|
|
2
|
+
import { extractErrorMsg } from '@vultisig/lib-utils/error/extractErrorMsg';
|
|
3
|
+
import { attempt } from '@vultisig/lib-utils/attempt';
|
|
4
|
+
const cardanoBroadcastUrl = `${rootApiUrl}/ada/`;
|
|
5
|
+
/** Cap a submit at 30s so a hung connection doesn't wedge the signer popup. */
|
|
6
|
+
const cardanoBroadcastTimeoutMs = 30_000;
|
|
7
|
+
const stripHashPrefix = (hash) => hash.replace(/^0x/i, '');
|
|
8
|
+
/**
|
|
9
|
+
* Broadcast a hex-encoded Cardano transaction CBOR via the Vultisig Ogmios JSON-RPC proxy.
|
|
10
|
+
*
|
|
11
|
+
* This low-level helper exposes the raw response so higher-level callers can
|
|
12
|
+
* distinguish "already-committed" (`rpcErrorCode === 3117`), mempool conflicts,
|
|
13
|
+
* etc. For the common "submit or throw" shape, use `submitCardanoCborTx`.
|
|
14
|
+
*/
|
|
15
|
+
export const submitCardanoCbor = async (cborHex) => {
|
|
16
|
+
const cleaned = cborHex.replace(/^0x/i, '').toLowerCase();
|
|
17
|
+
// Direct fetch: `queryUrl` auto-runs assertFetchResponse which throws before
|
|
18
|
+
// we can inspect the raw body or status.
|
|
19
|
+
const controller = new AbortController();
|
|
20
|
+
const timeoutId = setTimeout(() => controller.abort(), cardanoBroadcastTimeoutMs);
|
|
21
|
+
const fetchResult = await attempt(() => fetch(cardanoBroadcastUrl, {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
headers: { 'Content-Type': 'application/json' },
|
|
24
|
+
body: JSON.stringify({
|
|
25
|
+
jsonrpc: '2.0',
|
|
26
|
+
method: 'submitTransaction',
|
|
27
|
+
params: { transaction: { cbor: cleaned } },
|
|
28
|
+
id: 1,
|
|
29
|
+
}),
|
|
30
|
+
signal: controller.signal,
|
|
31
|
+
}));
|
|
32
|
+
clearTimeout(timeoutId);
|
|
33
|
+
if ('error' in fetchResult) {
|
|
34
|
+
const timedOut = controller.signal.aborted;
|
|
35
|
+
return {
|
|
36
|
+
txHash: null,
|
|
37
|
+
errorMessage: timedOut
|
|
38
|
+
? `Cardano broadcast timed out after ${cardanoBroadcastTimeoutMs}ms`
|
|
39
|
+
: extractErrorMsg(fetchResult.error),
|
|
40
|
+
rawResponse: '',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const response = fetchResult.data;
|
|
44
|
+
const bodyResult = await attempt(() => response.text());
|
|
45
|
+
if ('error' in bodyResult) {
|
|
46
|
+
return {
|
|
47
|
+
txHash: null,
|
|
48
|
+
errorMessage: extractErrorMsg(bodyResult.error),
|
|
49
|
+
rawResponse: '',
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const rawResponse = bodyResult.data;
|
|
53
|
+
const parsedResult = attempt(() => JSON.parse(rawResponse));
|
|
54
|
+
const parsed = 'data' in parsedResult ? parsedResult.data : null;
|
|
55
|
+
const txId = parsed?.result?.transaction?.id;
|
|
56
|
+
if (typeof txId === 'string' && txId.trim()) {
|
|
57
|
+
return {
|
|
58
|
+
txHash: stripHashPrefix(txId.trim()),
|
|
59
|
+
errorMessage: null,
|
|
60
|
+
rpcErrorCode: parsed?.error?.code,
|
|
61
|
+
rawResponse,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
txHash: null,
|
|
66
|
+
errorMessage: extractErrorMsg(parsed?.error ?? rawResponse),
|
|
67
|
+
rpcErrorCode: parsed?.error?.code,
|
|
68
|
+
rawResponse,
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=submitCardanoCbor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submitCardanoCbor.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/cardano/submit/submitCardanoCbor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cardano.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cardano.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAMvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"cardano.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cardano.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAMvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AASjD,eAAO,MAAM,kBAAkB,EAAE,mBAAmB,CAClD,UAAU,CAAC,OAAO,CA4BnB,CAAA"}
|
|
@@ -1,74 +1,22 @@
|
|
|
1
1
|
import { getCardanoTxHash } from '@vultisig/core-chain/tx/hash/resolvers/cardano';
|
|
2
|
-
import { rootApiUrl } from '@vultisig/core-config';
|
|
3
|
-
import { extractErrorMsg } from '@vultisig/lib-utils/error/extractErrorMsg';
|
|
4
2
|
import { isInError } from '@vultisig/lib-utils/error/isInError';
|
|
3
|
+
import { submitCardanoCbor } from '../../../chains/cardano/submit/submitCardanoCbor.js';
|
|
5
4
|
import { selectEncodedBytes } from './utxo.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
const extractTxHash = (response) => {
|
|
17
|
-
if (!response) {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
if (typeof response === 'string') {
|
|
21
|
-
const trimmed = response.trim();
|
|
22
|
-
return trimmed ? normalizeHash(trimmed) : null;
|
|
23
|
-
}
|
|
24
|
-
const txId = response.result?.transaction?.id;
|
|
25
|
-
if (typeof txId === 'string' && txId.trim()) {
|
|
26
|
-
return normalizeHash(txId.trim());
|
|
27
|
-
}
|
|
28
|
-
return null;
|
|
29
|
-
};
|
|
30
|
-
const extractError = (response, raw) => {
|
|
31
|
-
if (!response) {
|
|
32
|
-
return extractErrorMsg(raw);
|
|
33
|
-
}
|
|
34
|
-
if (typeof response === 'string') {
|
|
35
|
-
return extractErrorMsg(response);
|
|
36
|
-
}
|
|
37
|
-
return extractErrorMsg(response.error ?? raw);
|
|
38
|
-
};
|
|
5
|
+
/**
|
|
6
|
+
* Ogmios code for "transaction already known / in ledger". When the node
|
|
7
|
+
* reports this, we hash the tx locally to return the deterministic id.
|
|
8
|
+
*/
|
|
9
|
+
const alreadyCommittedCode = 3117;
|
|
39
10
|
export const broadcastCardanoTx = async ({ chain, tx }) => {
|
|
40
11
|
const encodedBytes = selectEncodedBytes(chain, tx);
|
|
41
12
|
const cborHex = Buffer.from(encodedBytes).toString('hex');
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
method: 'POST',
|
|
45
|
-
headers: {
|
|
46
|
-
'Content-Type': 'application/json',
|
|
47
|
-
},
|
|
48
|
-
body: JSON.stringify({
|
|
49
|
-
jsonrpc: '2.0',
|
|
50
|
-
method: 'submitTransaction',
|
|
51
|
-
params: {
|
|
52
|
-
transaction: {
|
|
53
|
-
cbor: cborHex,
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
id: 1,
|
|
57
|
-
}),
|
|
58
|
-
});
|
|
59
|
-
const responseText = await response.text();
|
|
60
|
-
const parsed = parseJson(responseText);
|
|
61
|
-
const rpcErrorCode = parsed && typeof parsed === 'object' && !Array.isArray(parsed)
|
|
62
|
-
? parsed.error?.code
|
|
63
|
-
: undefined;
|
|
64
|
-
if (rpcErrorCode === 3117) {
|
|
65
|
-
return normalizeHash(await getCardanoTxHash(tx));
|
|
66
|
-
}
|
|
67
|
-
const txHash = extractTxHash(parsed) ?? extractTxHash(responseText);
|
|
68
|
-
if (txHash) {
|
|
13
|
+
const { txHash, errorMessage, rpcErrorCode } = await submitCardanoCbor(cborHex);
|
|
14
|
+
if (txHash)
|
|
69
15
|
return txHash;
|
|
16
|
+
if (rpcErrorCode === alreadyCommittedCode) {
|
|
17
|
+
return (await getCardanoTxHash(tx)).replace(/^0x/i, '');
|
|
70
18
|
}
|
|
71
|
-
const error =
|
|
19
|
+
const error = errorMessage ?? 'unknown broadcast failure';
|
|
72
20
|
if (isInError(error, 'BadInputsUTxO', 'timed out', 'txn-mempool-conflict', 'already known')) {
|
|
73
21
|
return null;
|
|
74
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cardano.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cardano.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAA;AACjF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cardano.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/tx/broadcast/resolvers/cardano.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAA;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kDAAkD,CAAA;AAGpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAA;AAE3C;;;GAGG;AACH,MAAM,oBAAoB,GAAG,IAAI,CAAA;AAEjC,MAAM,CAAC,MAAM,kBAAkB,GAE3B,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE;IAC1B,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAClD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEzD,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAE/E,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IAEzB,IAAI,YAAY,KAAK,oBAAoB,EAAE,CAAC;QAC1C,OAAO,CAAC,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACzD,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,IAAI,2BAA2B,CAAA;IAEzD,IACE,SAAS,CACP,KAAK,EACL,eAAe,EACf,WAAW,EACX,sBAAsB,EACtB,eAAe,CAChB,EACD,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,oCAAoC,KAAK,EAAE,CAAC,CAAA;AAC9D,CAAC,CAAA"}
|