@gibs/bridge-sdk 1.19.0 → 1.20.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/dist/abis.js +0 -2
- package/dist/bridge-limits.js +0 -38
- package/dist/chain-info.js +0 -116
- package/dist/chain-names.js +0 -151
- package/dist/chains.js +0 -198
- package/dist/cjs/abis.js +0 -2
- package/dist/cjs/bridge-limits.js +0 -38
- package/dist/cjs/chain-info.js +0 -116
- package/dist/cjs/chain-names.js +0 -151
- package/dist/cjs/chains.js +0 -198
- package/dist/cjs/claims.js +0 -60
- package/dist/cjs/config.js +1 -208
- package/dist/cjs/consolidated-quote.js +0 -465
- package/dist/cjs/destination-calldata.js +0 -71
- package/dist/cjs/ecosystems.js +0 -183
- package/dist/cjs/execution.js +0 -92
- package/dist/cjs/fee-type.js +0 -1
- package/dist/cjs/hyperliquid-execution.js +0 -98
- package/dist/cjs/image-links.js +0 -108
- package/dist/cjs/lifi-execution-guard.js +65 -172
- package/dist/cjs/near-intents-conformance.js +0 -110
- package/dist/cjs/near-intents-route.js +0 -149
- package/dist/cjs/near-intents.js +0 -562
- package/dist/cjs/origin-deposit.js +0 -56
- package/dist/cjs/pre-quote.js +0 -80
- package/dist/cjs/prices.js +0 -113
- package/dist/cjs/providers.js +0 -83
- package/dist/cjs/quote-fees.js +0 -80
- package/dist/cjs/referral.js +0 -75
- package/dist/cjs/relay-currencies.js +0 -31
- package/dist/cjs/relay-depository.js +52 -77
- package/dist/cjs/relay-quote.js +0 -394
- package/dist/cjs/route-steps.js +0 -100
- package/dist/cjs/routing/amounts.js +0 -83
- package/dist/cjs/routing/candidate-route.js +0 -73
- package/dist/cjs/routing/candidate.js +0 -46
- package/dist/cjs/routing/carrier-provider-key.js +0 -27
- package/dist/cjs/routing/carriers/omnibridge.js +0 -120
- package/dist/cjs/routing/carriers/pulsex-paths.js +0 -57
- package/dist/cjs/routing/carriers/pulsex-split.js +0 -92
- package/dist/cjs/routing/carriers/pulsex.js +0 -279
- package/dist/cjs/routing/carriers/wrap.js +0 -57
- package/dist/cjs/routing/composed-route-quality.js +0 -95
- package/dist/cjs/routing/entry-chain-anchor.js +0 -27
- package/dist/cjs/routing/format.js +0 -50
- package/dist/cjs/routing/index.js +0 -28
- package/dist/cjs/routing/producers.js +0 -854
- package/dist/cjs/routing/providers.js +0 -27
- package/dist/cjs/routing/search/compose.js +0 -56
- package/dist/cjs/routing/search/graph.js +0 -364
- package/dist/cjs/routing/search/plan-route-data.js +0 -508
- package/dist/cjs/routing/search/score.js +0 -344
- package/dist/cjs/routing/swap-transactions.js +0 -74
- package/dist/cjs/routing/usd-value.js +0 -12
- package/dist/cjs/settings.js +1 -456
- package/dist/cjs/swap-venues.js +0 -17
- package/dist/cjs/ton-connect.js +0 -82
- package/dist/cjs/ton-execution.js +0 -6
- package/dist/cjs/ton.js +0 -42
- package/dist/cjs/tron-execution.js +0 -145
- package/dist/claims.js +0 -60
- package/dist/config.js +1 -211
- package/dist/consolidated-quote.js +0 -465
- package/dist/destination-calldata.js +0 -71
- package/dist/ecosystems.js +0 -183
- package/dist/execution.js +0 -92
- package/dist/fee-type.js +0 -2
- package/dist/hyperliquid-execution.js +0 -98
- package/dist/image-links.js +0 -108
- package/dist/lifi-execution-guard.js +65 -172
- package/dist/near-intents-conformance.js +0 -110
- package/dist/near-intents-route.js +0 -149
- package/dist/near-intents.js +0 -562
- package/dist/origin-deposit.js +0 -56
- package/dist/pre-quote.js +0 -80
- package/dist/prices.js +0 -113
- package/dist/providers.js +0 -83
- package/dist/quote-fees.js +0 -80
- package/dist/referral.js +0 -75
- package/dist/relay-currencies.js +0 -31
- package/dist/relay-depository.js +52 -77
- package/dist/relay-quote.js +0 -394
- package/dist/route-steps.js +0 -100
- package/dist/routing/amounts.js +0 -83
- package/dist/routing/candidate-route.js +0 -73
- package/dist/routing/candidate.js +0 -46
- package/dist/routing/carrier-provider-key.js +0 -27
- package/dist/routing/carriers/omnibridge.js +0 -120
- package/dist/routing/carriers/pulsex-paths.js +0 -57
- package/dist/routing/carriers/pulsex-split.js +0 -92
- package/dist/routing/carriers/pulsex.js +0 -279
- package/dist/routing/carriers/wrap.js +0 -57
- package/dist/routing/composed-route-quality.js +0 -95
- package/dist/routing/entry-chain-anchor.js +0 -27
- package/dist/routing/format.js +0 -50
- package/dist/routing/index.js +0 -28
- package/dist/routing/producers.js +0 -854
- package/dist/routing/providers.js +0 -27
- package/dist/routing/search/compose.js +0 -56
- package/dist/routing/search/graph.js +0 -364
- package/dist/routing/search/plan-route-data.js +0 -508
- package/dist/routing/search/score.js +0 -344
- package/dist/routing/swap-transactions.js +0 -74
- package/dist/routing/usd-value.js +0 -12
- package/dist/settings.js +1 -456
- package/dist/swap-venues.js +0 -17
- package/dist/ton-connect.js +0 -82
- package/dist/ton-execution.js +0 -6
- package/dist/ton.js +0 -42
- package/dist/tron-execution.js +0 -145
- package/package.json +3 -3
package/dist/swap-venues.js
CHANGED
|
@@ -1,24 +1,7 @@
|
|
|
1
1
|
import { defaultSwapVenues } from './config.js';
|
|
2
|
-
/**
|
|
3
|
-
* Merges caller venues over {@link defaultSwapVenues}. A chain present in
|
|
4
|
-
* `overrides` replaces the default list for that chain. A chain absent from
|
|
5
|
-
* `overrides` keeps its default list. An empty list switches swaps off on
|
|
6
|
-
* that chain. Neither input is changed; the result is frozen.
|
|
7
|
-
*
|
|
8
|
-
* @param overrides - the caller's venues, or undefined for the defaults
|
|
9
|
-
* @returns the venues to use
|
|
10
|
-
*/
|
|
11
2
|
export const resolveSwapVenues = (overrides) => {
|
|
12
3
|
if (overrides === undefined)
|
|
13
4
|
return defaultSwapVenues;
|
|
14
5
|
return Object.freeze({ ...defaultSwapVenues, ...overrides });
|
|
15
6
|
};
|
|
16
|
-
/**
|
|
17
|
-
* Finds the venue on a chain that has the given router.
|
|
18
|
-
*
|
|
19
|
-
* @param venues - the venues to search
|
|
20
|
-
* @param chainId - the numeric chain id
|
|
21
|
-
* @param router - the router address, in any letter case
|
|
22
|
-
* @returns the venue, or null when the chain has no venue with that router
|
|
23
|
-
*/
|
|
24
7
|
export const findSwapVenue = (venues, chainId, router) => venues[chainId]?.find((venue) => venue.router.toLowerCase() === router.toLowerCase()) ?? null;
|
package/dist/ton-connect.js
CHANGED
|
@@ -1,56 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Executing a deposit on The Open Network, as pure data, with no TON library.
|
|
3
|
-
*
|
|
4
|
-
* This module imports nothing outside the package, so it loads anywhere: a
|
|
5
|
-
* browser, Node, or a React Native app under Hermes, with no `Buffer` and no
|
|
6
|
-
* polyfill. It uses only `atob` and `btoa`, which Hermes provides. The one TON
|
|
7
|
-
* helper that needs `@ton/core`, the TEP-467 message hash, lives in
|
|
8
|
-
* `@gibs/bridge-sdk/ton` instead.
|
|
9
|
-
*
|
|
10
|
-
* Relay describes a deposit as a list of internal messages carrying `to`,
|
|
11
|
-
* `value`, `body` and a `bounce` flag. A connected wallet, however, is driven
|
|
12
|
-
* through the TON Connect protocol, whose request shape is different in one way
|
|
13
|
-
* that silently loses money:
|
|
14
|
-
*
|
|
15
|
-
* **TON Connect has no per-message `bounce` field.** A wallet derives whether a
|
|
16
|
-
* message bounces from the FORM OF THE ADDRESS — the bounceable `EQ…` prefix or
|
|
17
|
-
* the non-bounceable `UQ…` one. Passing Relay's address through unchanged while
|
|
18
|
-
* dropping its `bounce: false` therefore sends a deposit to the bounceable form,
|
|
19
|
-
* and the depository bounces the funds straight back to the sender. The transfer
|
|
20
|
-
* looks like it succeeded and the route never fills.
|
|
21
|
-
*
|
|
22
|
-
* {@link buildTonConnectRequest} folds `bounce` into the address so the flag
|
|
23
|
-
* cannot be dropped on the way to a wallet.
|
|
24
|
-
*
|
|
25
|
-
* Kept free of transport and of clock reads so it is fully testable: nothing
|
|
26
|
-
* here signs, fetches, or calls `Date.now`. The caller supplies the deadline and
|
|
27
|
-
* performs the request.
|
|
28
|
-
*
|
|
29
|
-
* The rules encoded here are those of Relay's own wallet adapter, which is the
|
|
30
|
-
* only reference implementation of this mapping.
|
|
31
|
-
*/
|
|
32
|
-
/**
|
|
33
|
-
* The TON Connect network identifier for mainnet. Relay bridges only mainnet, so
|
|
34
|
-
* a request is always tagged with this.
|
|
35
|
-
*/
|
|
36
1
|
export const tonConnectMainnetNetwork = '-239';
|
|
37
|
-
/** How long a request stays valid by default, in seconds, matching Relay's adapter. */
|
|
38
2
|
export const tonConnectDefaultValidForSeconds = 300;
|
|
39
|
-
/** Address tag byte for the bounceable (`EQ…`) form. */
|
|
40
3
|
const bounceableTag = 0x11;
|
|
41
|
-
/** Address tag byte for the non-bounceable (`UQ…`) form. */
|
|
42
4
|
const nonBounceableTag = 0x51;
|
|
43
|
-
/** Bit set on the tag byte for testnet-only addresses (`kQ…` / `0Q…`). */
|
|
44
5
|
const testnetTagFlag = 0x80;
|
|
45
|
-
/** A friendly address is a 36-byte structure: tag, workchain, hash, checksum. */
|
|
46
6
|
const friendlyAddressByteLength = 36;
|
|
47
|
-
/** An account identifier is always 32 bytes, in every address form. */
|
|
48
7
|
const accountHashByteLength = 32;
|
|
49
|
-
/**
|
|
50
|
-
* Cyclic redundancy check (16-bit, the XModem variant) over an address body.
|
|
51
|
-
* The Open Network appends it to every friendly address, and a re-encoded
|
|
52
|
-
* address whose checksum is not recomputed is rejected by wallets as malformed.
|
|
53
|
-
*/
|
|
54
8
|
const checksum = (data) => {
|
|
55
9
|
let remainder = 0;
|
|
56
10
|
for (const byte of data) {
|
|
@@ -62,7 +16,6 @@ const checksum = (data) => {
|
|
|
62
16
|
}
|
|
63
17
|
return remainder;
|
|
64
18
|
};
|
|
65
|
-
/** Decodes the url-safe base64 alphabet the friendly address form uses. */
|
|
66
19
|
const decodeBase64Url = (value) => {
|
|
67
20
|
const standard = value.replaceAll('-', '+').replaceAll('_', '/');
|
|
68
21
|
const padded = standard.padEnd(Math.ceil(standard.length / 4) * 4, '=');
|
|
@@ -74,7 +27,6 @@ const decodeBase64Url = (value) => {
|
|
|
74
27
|
return null;
|
|
75
28
|
}
|
|
76
29
|
};
|
|
77
|
-
/** Encodes bytes back into the url-safe, unpadded base64 form. */
|
|
78
30
|
const encodeBase64Url = (bytes) => {
|
|
79
31
|
let binary = '';
|
|
80
32
|
for (const byte of bytes) {
|
|
@@ -100,7 +52,6 @@ const parseRawAddress = (value) => {
|
|
|
100
52
|
}
|
|
101
53
|
hash[index] = byte;
|
|
102
54
|
}
|
|
103
|
-
// The raw form carries no network tag, so mainnet is the only safe assumption.
|
|
104
55
|
return { workchain, hash, testOnly: false };
|
|
105
56
|
};
|
|
106
57
|
const parseFriendlyAddress = (value) => {
|
|
@@ -109,8 +60,6 @@ const parseFriendlyAddress = (value) => {
|
|
|
109
60
|
return null;
|
|
110
61
|
}
|
|
111
62
|
const body = bytes.subarray(0, friendlyAddressByteLength - 2);
|
|
112
|
-
// Every index below is in range: the length was checked to be exactly
|
|
113
|
-
// `friendlyAddressByteLength` above, so the non-null assertions are sound.
|
|
114
63
|
const stated = (bytes[friendlyAddressByteLength - 2] << 8) | bytes[friendlyAddressByteLength - 1];
|
|
115
64
|
if (checksum(body) !== stated) {
|
|
116
65
|
return null;
|
|
@@ -122,29 +71,12 @@ const parseFriendlyAddress = (value) => {
|
|
|
122
71
|
}
|
|
123
72
|
const workchainByte = bytes[1];
|
|
124
73
|
return {
|
|
125
|
-
// The masterchain is workchain -1, which travels as the byte 0xff.
|
|
126
74
|
workchain: workchainByte === 0xff ? -1 : workchainByte,
|
|
127
75
|
hash: bytes.slice(2, 2 + accountHashByteLength),
|
|
128
76
|
testOnly: (tag & testnetTagFlag) !== 0,
|
|
129
77
|
};
|
|
130
78
|
};
|
|
131
|
-
/**
|
|
132
|
-
* Parses either address form The Open Network uses.
|
|
133
|
-
*
|
|
134
|
-
* @param value - a friendly (`EQ…`/`UQ…`) or raw (`0:…`) address
|
|
135
|
-
* @returns the address parts, or null when it is neither form or fails its checksum
|
|
136
|
-
*/
|
|
137
79
|
export const parseTonAddress = (value) => value.includes(':') ? parseRawAddress(value) : parseFriendlyAddress(value);
|
|
138
|
-
/**
|
|
139
|
-
* Re-encodes an address into the friendly form matching a bounce setting.
|
|
140
|
-
*
|
|
141
|
-
* This is the whole point of the module: the bounce flag has nowhere else to
|
|
142
|
-
* live in a TON Connect request, so it has to be carried by the address itself.
|
|
143
|
-
*
|
|
144
|
-
* @param address - the address in either form
|
|
145
|
-
* @param options.bounceable - whether the message may bounce back to the sender
|
|
146
|
-
* @returns the friendly address, or null when the input cannot be parsed
|
|
147
|
-
*/
|
|
148
80
|
export const encodeTonAddress = (address, { bounceable }) => {
|
|
149
81
|
const parsed = parseTonAddress(address);
|
|
150
82
|
if (parsed === null) {
|
|
@@ -160,17 +92,6 @@ export const encodeTonAddress = (address, { bounceable }) => {
|
|
|
160
92
|
bytes[friendlyAddressByteLength - 1] = stated & 0xff;
|
|
161
93
|
return encodeBase64Url(bytes);
|
|
162
94
|
};
|
|
163
|
-
/**
|
|
164
|
-
* Builds the TON Connect request for a deposit.
|
|
165
|
-
*
|
|
166
|
-
* @param deposit - the parsed origin deposit
|
|
167
|
-
* @param options.validUntil - unix seconds after which the request expires.
|
|
168
|
-
* Supplied by the caller rather than read from a clock here so the transform
|
|
169
|
-
* stays pure; {@link tonConnectDefaultValidForSeconds} is the usual offset.
|
|
170
|
-
* @returns the request, or null when the deposit carries no messages or any
|
|
171
|
-
* destination address cannot be re-encoded — never a request whose bounce
|
|
172
|
-
* setting has been silently dropped
|
|
173
|
-
*/
|
|
174
95
|
export const buildTonConnectRequest = (deposit, { validUntil }) => {
|
|
175
96
|
if (deposit.messages.length === 0) {
|
|
176
97
|
return null;
|
|
@@ -178,8 +99,6 @@ export const buildTonConnectRequest = (deposit, { validUntil }) => {
|
|
|
178
99
|
const messages = [];
|
|
179
100
|
for (const message of deposit.messages) {
|
|
180
101
|
const address = encodeTonAddress(message.to, { bounceable: message.bounce });
|
|
181
|
-
// Refuse rather than fall back to the unencoded address: the fallback is
|
|
182
|
-
// exactly the bounce-losing behaviour this module exists to prevent.
|
|
183
102
|
if (address === null) {
|
|
184
103
|
return null;
|
|
185
104
|
}
|
|
@@ -189,7 +108,6 @@ export const buildTonConnectRequest = (deposit, { validUntil }) => {
|
|
|
189
108
|
...(message.body ? { payload: message.body } : {}),
|
|
190
109
|
});
|
|
191
110
|
}
|
|
192
|
-
// `messages[0]` is present: the empty case returned null above.
|
|
193
111
|
const from = deposit.messages[0].from;
|
|
194
112
|
return {
|
|
195
113
|
validUntil,
|
package/dist/ton-execution.js
CHANGED
|
@@ -1,7 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The original name of `@gibs/bridge-sdk/ton`, kept so existing imports work.
|
|
3
|
-
*
|
|
4
|
-
* @deprecated Import from `@gibs/bridge-sdk/ton` for the full TON surface, or
|
|
5
|
-
* from `@gibs/bridge-sdk/ton-connect` for the helpers that need no TON library.
|
|
6
|
-
*/
|
|
7
1
|
export * from './ton.js';
|
package/dist/ton.js
CHANGED
|
@@ -1,57 +1,16 @@
|
|
|
1
1
|
import { Cell, beginCell, loadMessage, storeMessage } from '@ton/core';
|
|
2
|
-
/**
|
|
3
|
-
* Everything the bridge SDK offers for The Open Network, in one entry point.
|
|
4
|
-
*
|
|
5
|
-
* It re-exports the pure TON Connect helpers from `./ton-connect.js` and adds
|
|
6
|
-
* {@link tonExternalMessageHash}, the only helper that needs `@ton/core`.
|
|
7
|
-
*
|
|
8
|
-
* Kept apart from the root entry point on purpose. `@ton/core` uses Node's
|
|
9
|
-
* `Buffer`, and its `@ton/crypto` dependency resolves, under React Native, to a
|
|
10
|
-
* build that requires `expo-crypto`. An application that bridges only between
|
|
11
|
-
* Ethereum-style chains never imports this file, so it never pays for either.
|
|
12
|
-
*/
|
|
13
2
|
export * from './ton-connect.js';
|
|
14
|
-
/**
|
|
15
|
-
* Derives the transaction identifier from a wallet's `sendTransaction` response.
|
|
16
|
-
*
|
|
17
|
-
* A wallet answers with a `boc`: the base64 bag-of-cells of the signed
|
|
18
|
-
* external-in message it broadcast — NOT the resulting transaction, and NOT a
|
|
19
|
-
* hash. The identifier explorers and indexers (toncenter, TonAPI) resolve a
|
|
20
|
-
* transaction by is the hash of that external message, but it must be the
|
|
21
|
-
* NORMALIZED hash of TEP-467, not the hash of the bytes the wallet happened to
|
|
22
|
-
* send.
|
|
23
|
-
*
|
|
24
|
-
* The distinction is the whole point, and getting it wrong loses a resume record
|
|
25
|
-
* for real funds. An external-in message can be serialized several equivalent
|
|
26
|
-
* ways — a wallet may or may not include its own `src`, may set a non-zero
|
|
27
|
-
* `import_fee`, may attach a `stateInit`, may store the body inline or as a
|
|
28
|
-
* reference. The raw cell hash changes with each of those wallet-specific
|
|
29
|
-
* choices, so it frequently does NOT match what an indexer keyed the same
|
|
30
|
-
* transaction under. TEP-467 rebuilds the message with those variable fields
|
|
31
|
-
* stripped (`src` to none, `import_fee` to zero, `init` dropped, body forced to a
|
|
32
|
-
* reference) so the hash is stable across wallets and matches the indexers.
|
|
33
|
-
*
|
|
34
|
-
* @param boc - the wallet's base64 `boc` field from `sendTransaction`
|
|
35
|
-
* @returns the 64-character hex normalized hash, or null when the input is not a
|
|
36
|
-
* parseable external-in message
|
|
37
|
-
*/
|
|
38
3
|
export const tonExternalMessageHash = (boc) => {
|
|
39
4
|
try {
|
|
40
5
|
const message = loadMessage(Cell.fromBase64(boc).beginParse());
|
|
41
|
-
// Only an external-in message has a normalized form; an internal message or
|
|
42
|
-
// a bare cell is not the wallet's broadcast envelope and cannot be keyed.
|
|
43
6
|
if (message.info.type !== 'external-in') {
|
|
44
7
|
return null;
|
|
45
8
|
}
|
|
46
9
|
const normalized = {
|
|
47
10
|
...message,
|
|
48
|
-
// Dropped by TEP-467 so a wallet-attached stateInit does not move the hash.
|
|
49
11
|
init: null,
|
|
50
|
-
// `src` to addr_none (undefined) and the fee to zero: both are the sender's
|
|
51
|
-
// to choose and neither is part of what identifies the message.
|
|
52
12
|
info: { ...message.info, src: undefined, importFee: 0n },
|
|
53
13
|
};
|
|
54
|
-
// `forceRef` stores the body as a reference, as the normalized form requires.
|
|
55
14
|
return beginCell()
|
|
56
15
|
.store(storeMessage(normalized, { forceRef: true }))
|
|
57
16
|
.endCell()
|
|
@@ -59,7 +18,6 @@ export const tonExternalMessageHash = (boc) => {
|
|
|
59
18
|
.toString('hex');
|
|
60
19
|
}
|
|
61
20
|
catch {
|
|
62
|
-
// A malformed base64 payload or a cell tree that is not a message at all.
|
|
63
21
|
return null;
|
|
64
22
|
}
|
|
65
23
|
};
|
package/dist/tron-execution.js
CHANGED
|
@@ -1,69 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Executing a deposit on Tron, as pure data.
|
|
3
|
-
*
|
|
4
|
-
* Relay does not return a broadcastable Tron transaction. It returns the
|
|
5
|
-
* *parameters* of a `TriggerSmartContract` call — owner, contract, call value
|
|
6
|
-
* and calldata — and nothing else. A Tron transaction additionally needs a
|
|
7
|
-
* reference block, an expiration and a fee limit, none of which Relay supplies.
|
|
8
|
-
* Those are produced by asking a full node to build the transaction, which is
|
|
9
|
-
* what {@link buildTriggerSmartContractRequest} constructs the body for. The
|
|
10
|
-
* node answers with an UNSIGNED transaction; the wallet signs it and a second
|
|
11
|
-
* call broadcasts it.
|
|
12
|
-
*
|
|
13
|
-
* Three details of that exchange lose money or mislead if handled naively:
|
|
14
|
-
*
|
|
15
|
-
* **The `visible` flag defaults to true.** A node reads addresses as base58
|
|
16
|
-
* unless told otherwise, but Relay returns them as hex with Tron's `41` prefix.
|
|
17
|
-
* Omitting the flag therefore hands base58-parsing a hex string. The request
|
|
18
|
-
* built here always states `visible: false` rather than relying on a default
|
|
19
|
-
* that is the opposite of what the payload contains.
|
|
20
|
-
*
|
|
21
|
-
* **`fee_limit` is required and Relay omits it.** It caps the energy the caller
|
|
22
|
-
* will pay for. Set too low, the call runs out of energy, reverts, and the
|
|
23
|
-
* energy already burned is NOT refunded — the deposit fails and costs the user
|
|
24
|
-
* anyway.
|
|
25
|
-
*
|
|
26
|
-
* **A rejected call still answers HTTP 200**, with the reason hex-encoded in
|
|
27
|
-
* `result.message`. Reading the status code alone reports a failed deposit as a
|
|
28
|
-
* success, and printing the message unmodified shows the user a wall of hex.
|
|
29
|
-
* {@link tronErrorMessage} decodes it.
|
|
30
|
-
*
|
|
31
|
-
* Kept free of transport and of clock reads so it is fully testable: nothing
|
|
32
|
-
* here signs, fetches, or calls `Date.now`. The caller performs the requests.
|
|
33
|
-
*/
|
|
34
|
-
/** Path of the full-node endpoint that builds an unsigned contract call. */
|
|
35
1
|
export const tronTriggerSmartContractPath = '/wallet/triggersmartcontract';
|
|
36
|
-
/**
|
|
37
|
-
* The fee limit used when a caller states none, in sun (1 TRX = 1,000,000 sun).
|
|
38
|
-
*
|
|
39
|
-
* Thirty TRX, matching Relay's own wallet adapter, which is the only reference
|
|
40
|
-
* implementation of this deposit path. It is an upper bound rather than a
|
|
41
|
-
* charge: unused energy is not taken, so the cost of setting it generously is
|
|
42
|
-
* only that the wallet shows a larger worst case.
|
|
43
|
-
*/
|
|
44
2
|
export const defaultTronFeeLimitSun = 30_000_000;
|
|
45
|
-
/**
|
|
46
|
-
* The largest fee limit a node accepts, in sun — 15,000 TRX. Documented as a
|
|
47
|
-
* hard protocol cap, so a request above it is rejected outright rather than
|
|
48
|
-
* clamped.
|
|
49
|
-
*/
|
|
50
3
|
export const maximumTronFeeLimitSun = 15_000_000_000;
|
|
51
|
-
/**
|
|
52
|
-
* Tron's `41` address prefix, the hex form's equivalent of the base58 `T`.
|
|
53
|
-
*/
|
|
54
4
|
const tronHexAddressPrefix = '41';
|
|
55
|
-
/** A hex address is the prefix byte plus a twenty-byte account identifier. */
|
|
56
5
|
const tronHexAddressLength = 42;
|
|
57
|
-
/**
|
|
58
|
-
* Normalizes a Tron hex address for comparison.
|
|
59
|
-
*
|
|
60
|
-
* Wallets and quotes disagree on casing, and Relay's payload is not guaranteed
|
|
61
|
-
* to match what a wallet reports even when both name the same account.
|
|
62
|
-
*
|
|
63
|
-
* @param value - an address in Tron's `41`-prefixed hex form, in any casing,
|
|
64
|
-
* optionally written with a `0x` prefix
|
|
65
|
-
* @returns the lowercase `41` form, or null when the value is not that form
|
|
66
|
-
*/
|
|
67
6
|
export const normalizeTronHexAddress = (value) => {
|
|
68
7
|
const withoutPrefix = value.trim().replace(/^0x/i, '').toLowerCase();
|
|
69
8
|
if (withoutPrefix.length !== tronHexAddressLength) {
|
|
@@ -74,50 +13,13 @@ export const normalizeTronHexAddress = (value) => {
|
|
|
74
13
|
}
|
|
75
14
|
return /^[0-9a-f]+$/.test(withoutPrefix) ? withoutPrefix : null;
|
|
76
15
|
};
|
|
77
|
-
/**
|
|
78
|
-
* Whether two Tron hex addresses name the same account.
|
|
79
|
-
*
|
|
80
|
-
* Used to check a deposit's owner against the connected wallet before signing.
|
|
81
|
-
* A mismatch means the quote was built for a different account, and signing it
|
|
82
|
-
* would spend from an account the user did not choose — or simply fail after
|
|
83
|
-
* the user has already approved.
|
|
84
|
-
*
|
|
85
|
-
* @param left - an address in Tron's `41`-prefixed hex form
|
|
86
|
-
* @param right - an address in the same form
|
|
87
|
-
* @returns true only when both parse and name the same account
|
|
88
|
-
*/
|
|
89
16
|
export const isSameTronAccount = (left, right) => {
|
|
90
17
|
const normalizedLeft = normalizeTronHexAddress(left);
|
|
91
18
|
const normalizedRight = normalizeTronHexAddress(right);
|
|
92
19
|
return normalizedLeft !== null && normalizedLeft === normalizedRight;
|
|
93
20
|
};
|
|
94
|
-
/**
|
|
95
|
-
* Strips the `0x` prefix Tron calldata never carries.
|
|
96
|
-
*
|
|
97
|
-
* Relay documents this field as bare hex, but its own adapter strips the prefix
|
|
98
|
-
* defensively, and a prefixed value is parsed by a node as calldata beginning
|
|
99
|
-
* with the bytes `0x` rather than being rejected — a silently wrong call.
|
|
100
|
-
*/
|
|
101
21
|
const bareHex = (value) => value.replace(/^0x/i, '').toLowerCase();
|
|
102
|
-
/**
|
|
103
|
-
* Whether a numeric amount survives the trip through JSON as an exact integer.
|
|
104
|
-
*
|
|
105
|
-
* Sun amounts are 64-bit on the wire but JSON carries them as doubles, so a
|
|
106
|
-
* large enough value would be silently rounded — into a different amount of
|
|
107
|
-
* money than the one that was quoted.
|
|
108
|
-
*/
|
|
109
22
|
const isExactInteger = (value) => value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER);
|
|
110
|
-
/**
|
|
111
|
-
* Builds the body that asks a full node to construct the unsigned deposit.
|
|
112
|
-
*
|
|
113
|
-
* @param deposit - the parsed origin deposit
|
|
114
|
-
* @param options.feeLimitSun - the energy spending cap in sun; defaults to
|
|
115
|
-
* {@link defaultTronFeeLimitSun}
|
|
116
|
-
* @returns the request body, or null when the deposit names an address that is
|
|
117
|
-
* not Tron hex, carries a call value that cannot be represented exactly, or
|
|
118
|
-
* the fee limit is outside what a node accepts — never a body that would be
|
|
119
|
-
* built against a default `visible` the payload contradicts
|
|
120
|
-
*/
|
|
121
23
|
export const buildTriggerSmartContractRequest = (deposit, { feeLimitSun = defaultTronFeeLimitSun } = {}) => {
|
|
122
24
|
const ownerAddress = normalizeTronHexAddress(deposit.ownerAddress);
|
|
123
25
|
const contractAddress = normalizeTronHexAddress(deposit.contractAddress);
|
|
@@ -139,14 +41,6 @@ export const buildTriggerSmartContractRequest = (deposit, { feeLimitSun = defaul
|
|
|
139
41
|
visible: false,
|
|
140
42
|
};
|
|
141
43
|
};
|
|
142
|
-
/**
|
|
143
|
-
* Decodes a node's hex-encoded failure message.
|
|
144
|
-
*
|
|
145
|
-
* A node reports why it refused a call in `result.message`, hex-encoded — the
|
|
146
|
-
* bytes `4e6f20636f6e7472616374…` rather than "No contract or not a valid smart
|
|
147
|
-
* contract". Broadcast failures report plain text in the same field, so both
|
|
148
|
-
* are handled and a value that is not hex is passed through unchanged.
|
|
149
|
-
*/
|
|
150
44
|
const decodeTronMessage = (value) => {
|
|
151
45
|
const trimmed = value.trim();
|
|
152
46
|
if (trimmed.length === 0 || trimmed.length % 2 !== 0 || !/^[0-9a-fA-F]+$/.test(trimmed)) {
|
|
@@ -156,26 +50,16 @@ const decodeTronMessage = (value) => {
|
|
|
156
50
|
for (let index = 0; index < trimmed.length; index += 2) {
|
|
157
51
|
decoded += String.fromCharCode(Number.parseInt(trimmed.slice(index, index + 2), 16));
|
|
158
52
|
}
|
|
159
|
-
// A hex string that decodes to control characters was a number, not a
|
|
160
|
-
// message — return the original rather than a string of unprintable bytes.
|
|
161
53
|
return /^[\x20-\x7e]*$/.test(decoded) ? decoded : trimmed;
|
|
162
54
|
};
|
|
163
55
|
const asRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
164
56
|
? value
|
|
165
57
|
: null;
|
|
166
|
-
/**
|
|
167
|
-
* Extracts a node's failure reason from either endpoint's response.
|
|
168
|
-
*
|
|
169
|
-
* @param payload - the parsed response body
|
|
170
|
-
* @returns the decoded message, or null when the response reports no failure
|
|
171
|
-
*/
|
|
172
58
|
export const tronErrorMessage = (payload) => {
|
|
173
59
|
const body = asRecord(payload);
|
|
174
60
|
if (body === null) {
|
|
175
61
|
return null;
|
|
176
62
|
}
|
|
177
|
-
// The build endpoint nests its outcome under `result`; the broadcast endpoint
|
|
178
|
-
// reports at the top level.
|
|
179
63
|
const nested = asRecord(body.result);
|
|
180
64
|
const message = nested?.message ?? body.message;
|
|
181
65
|
if (typeof message !== 'string') {
|
|
@@ -184,17 +68,6 @@ export const tronErrorMessage = (payload) => {
|
|
|
184
68
|
const decoded = decodeTronMessage(message);
|
|
185
69
|
return decoded.length === 0 ? null : decoded;
|
|
186
70
|
};
|
|
187
|
-
/**
|
|
188
|
-
* Reads the unsigned transaction out of a build response.
|
|
189
|
-
*
|
|
190
|
-
* The response carries the transaction at the top level alongside a `result`
|
|
191
|
-
* object stating whether the build succeeded, so the presence of a `txID` is
|
|
192
|
-
* not on its own evidence of success.
|
|
193
|
-
*
|
|
194
|
-
* @param payload - the parsed `/wallet/triggersmartcontract` response
|
|
195
|
-
* @returns the unsigned transaction to hand a wallet, or null when the node
|
|
196
|
-
* refused the call
|
|
197
|
-
*/
|
|
198
71
|
export const readTriggerSmartContractResponse = (payload) => {
|
|
199
72
|
const body = asRecord(payload);
|
|
200
73
|
if (body === null) {
|
|
@@ -210,24 +83,6 @@ export const readTriggerSmartContractResponse = (payload) => {
|
|
|
210
83
|
}
|
|
211
84
|
return transaction;
|
|
212
85
|
};
|
|
213
|
-
/**
|
|
214
|
-
* Reads the transaction identifier out of a broadcast response.
|
|
215
|
-
*
|
|
216
|
-
* GOTCHA: a rejected broadcast answers HTTP 200, and `result` is OMITTED rather
|
|
217
|
-
* than set to false. Testing `result === false` therefore never fires, and
|
|
218
|
-
* trusting the status code records a deposit that never entered a block. Only
|
|
219
|
-
* an explicit `result: true` is accepted here.
|
|
220
|
-
*
|
|
221
|
-
* The identifier is read from `txid` where a node reports it, falling back to
|
|
222
|
-
* the echoed transaction's `txID`. The two spellings differ by casing and by
|
|
223
|
-
* position: a node answers `txid`, while a wallet library that echoes the
|
|
224
|
-
* transaction it broadcast carries `txID` inside it. Accepting only the first
|
|
225
|
-
* would report an accepted broadcast as a failure whenever the caller is one of
|
|
226
|
-
* those libraries.
|
|
227
|
-
*
|
|
228
|
-
* @param payload - the parsed `/wallet/broadcasttransaction` response
|
|
229
|
-
* @returns the transaction identifier, or null when the broadcast was refused
|
|
230
|
-
*/
|
|
231
86
|
export const readBroadcastResponse = (payload) => {
|
|
232
87
|
const body = asRecord(payload);
|
|
233
88
|
if (body === null || body.result !== true) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gibs/bridge-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.0",
|
|
4
4
|
"description": "Build and price cross-chain transfers between PulseChain, Ethereum, and Binance Smart Chain.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ethereum",
|
|
@@ -1007,8 +1007,8 @@
|
|
|
1007
1007
|
"test:live:near-intents": "../../scripts/near-intents-live.sh"
|
|
1008
1008
|
},
|
|
1009
1009
|
"dependencies": {
|
|
1010
|
-
"@gibs/abis": "^1.
|
|
1011
|
-
"@gibs/common": "^1.
|
|
1010
|
+
"@gibs/abis": "^1.20.0",
|
|
1011
|
+
"@gibs/common": "^1.20.0",
|
|
1012
1012
|
"@ton/core": "^0.63.1",
|
|
1013
1013
|
"@ton/crypto": "^3.3.0"
|
|
1014
1014
|
},
|