@defuse-protocol/intents-sdk 0.64.0 → 0.64.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/dist/src/intents/intent-hashes/ton-connect.cjs +4 -20
- package/dist/src/intents/intent-hashes/ton-connect.js +4 -20
- package/dist/src/lib/ton-address.cjs +74 -0
- package/dist/src/lib/ton-address.js +69 -0
- package/dist/src/lib/validateAddress.cjs +5 -19
- package/dist/src/lib/validateAddress.js +6 -20
- package/package.json +2 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('../../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_ton_address = require('../../lib/ton-address.cjs');
|
|
2
3
|
let _noble_hashes_sha2 = require("@noble/hashes/sha2");
|
|
3
4
|
|
|
4
5
|
//#region src/intents/intent-hashes/ton-connect.ts
|
|
@@ -13,27 +14,10 @@ function numberToBigEndian(num, bytes) {
|
|
|
13
14
|
}
|
|
14
15
|
return result;
|
|
15
16
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Parse TON address string to TonAddress object
|
|
18
|
-
* Supports raw format: "workchain:address_hex"
|
|
19
|
-
* Example: "0:f4809e5ffac9dc42a6b1d94c5e74ad5fd86378de675c805f2274d0055cbc9378"
|
|
20
|
-
*
|
|
21
|
-
* @param addressString - TON address string in raw format
|
|
22
|
-
* @returns Parsed TonAddress object
|
|
23
|
-
*/
|
|
24
17
|
function parseTonAddress(addressString) {
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
if (Number.isNaN(workchainId)) throw new Error(`Invalid workchain ID: ${parts[0]}`);
|
|
29
|
-
const addressHex = parts[1].startsWith("0x") ? parts[1].slice(2) : parts[1];
|
|
30
|
-
if (addressHex.length !== 64) throw new Error(`Invalid address length: expected 64 hex characters, got ${addressHex.length}`);
|
|
31
|
-
const address = new Uint8Array(32);
|
|
32
|
-
for (let i = 0; i < 32; i++) address[i] = parseInt(addressHex.slice(i * 2, i * 2 + 2), 16);
|
|
33
|
-
return {
|
|
34
|
-
workchainId,
|
|
35
|
-
address
|
|
36
|
-
};
|
|
18
|
+
const parsed = require_ton_address.tryParseTonAddress(addressString);
|
|
19
|
+
if (parsed === null) throw new Error(`Invalid TON address: ${addressString}`);
|
|
20
|
+
return parsed;
|
|
37
21
|
}
|
|
38
22
|
/**
|
|
39
23
|
* Compute the SHA-256 hash of a TON Connect payload
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { tryParseTonAddress } from "../../lib/ton-address.js";
|
|
1
2
|
import { sha256 } from "@noble/hashes/sha2";
|
|
2
3
|
|
|
3
4
|
//#region src/intents/intent-hashes/ton-connect.ts
|
|
@@ -12,27 +13,10 @@ function numberToBigEndian(num, bytes) {
|
|
|
12
13
|
}
|
|
13
14
|
return result;
|
|
14
15
|
}
|
|
15
|
-
/**
|
|
16
|
-
* Parse TON address string to TonAddress object
|
|
17
|
-
* Supports raw format: "workchain:address_hex"
|
|
18
|
-
* Example: "0:f4809e5ffac9dc42a6b1d94c5e74ad5fd86378de675c805f2274d0055cbc9378"
|
|
19
|
-
*
|
|
20
|
-
* @param addressString - TON address string in raw format
|
|
21
|
-
* @returns Parsed TonAddress object
|
|
22
|
-
*/
|
|
23
16
|
function parseTonAddress(addressString) {
|
|
24
|
-
const
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
if (Number.isNaN(workchainId)) throw new Error(`Invalid workchain ID: ${parts[0]}`);
|
|
28
|
-
const addressHex = parts[1].startsWith("0x") ? parts[1].slice(2) : parts[1];
|
|
29
|
-
if (addressHex.length !== 64) throw new Error(`Invalid address length: expected 64 hex characters, got ${addressHex.length}`);
|
|
30
|
-
const address = new Uint8Array(32);
|
|
31
|
-
for (let i = 0; i < 32; i++) address[i] = parseInt(addressHex.slice(i * 2, i * 2 + 2), 16);
|
|
32
|
-
return {
|
|
33
|
-
workchainId,
|
|
34
|
-
address
|
|
35
|
-
};
|
|
17
|
+
const parsed = tryParseTonAddress(addressString);
|
|
18
|
+
if (parsed === null) throw new Error(`Invalid TON address: ${addressString}`);
|
|
19
|
+
return parsed;
|
|
36
20
|
}
|
|
37
21
|
/**
|
|
38
22
|
* Compute the SHA-256 hash of a TON Connect payload
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let _scure_base = require("@scure/base");
|
|
3
|
+
|
|
4
|
+
//#region src/lib/ton-address.ts
|
|
5
|
+
/**
|
|
6
|
+
* Tag byte for user-friendly TON addresses. Bit 7 sets testnet, bit 6 sets
|
|
7
|
+
* non-bounceable. See https://docs.ton.org/learn/overviews/addresses#user-friendly-address
|
|
8
|
+
*/
|
|
9
|
+
const TON_ADDRESS_TAG_BOUNCEABLE_MAINNET = 17;
|
|
10
|
+
const TON_ADDRESS_TAG_NON_BOUNCEABLE_MAINNET = 81;
|
|
11
|
+
/**
|
|
12
|
+
* Real TON only uses these two workchains. Other values parse fine but no
|
|
13
|
+
* wallet emits them, so the validator treats them as typos.
|
|
14
|
+
*/
|
|
15
|
+
const TON_WORKCHAIN_BASECHAIN = 0;
|
|
16
|
+
const TON_WORKCHAIN_MASTERCHAIN = -1;
|
|
17
|
+
const TON_USER_FRIENDLY_LENGTH = 36;
|
|
18
|
+
function crc16ccitt(data) {
|
|
19
|
+
let crc = 0;
|
|
20
|
+
for (const byte of data) {
|
|
21
|
+
crc ^= byte << 8;
|
|
22
|
+
for (let i = 0; i < 8; i++) crc = crc & 32768 ? crc << 1 ^ 4129 : crc << 1;
|
|
23
|
+
crc &= 65535;
|
|
24
|
+
}
|
|
25
|
+
return [crc >> 8 & 255, crc & 255];
|
|
26
|
+
}
|
|
27
|
+
function parseTonUserFriendlyAddress(s) {
|
|
28
|
+
const normalized = s.replace(/\+/g, "-").replace(/\//g, "_");
|
|
29
|
+
let data;
|
|
30
|
+
try {
|
|
31
|
+
data = _scure_base.base64urlnopad.decode(normalized);
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
if (data.length !== TON_USER_FRIENDLY_LENGTH) return null;
|
|
36
|
+
const [hi, lo] = crc16ccitt(data.subarray(0, 34));
|
|
37
|
+
if (data[34] !== hi || data[35] !== lo) return null;
|
|
38
|
+
const tag = data[0];
|
|
39
|
+
const wcByte = data[1];
|
|
40
|
+
return {
|
|
41
|
+
tag,
|
|
42
|
+
workchainId: wcByte > 127 ? wcByte - 256 : wcByte,
|
|
43
|
+
address: data.slice(2, 34)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const RAW_HEX_LENGTH = 64;
|
|
47
|
+
function parseTonRawAddress(s) {
|
|
48
|
+
const parts = s.split(":");
|
|
49
|
+
if (parts.length !== 2) return null;
|
|
50
|
+
const workchainId = parseInt(parts[0], 10);
|
|
51
|
+
if (Number.isNaN(workchainId)) return null;
|
|
52
|
+
let hex = parts[1];
|
|
53
|
+
if (hex.startsWith("0x")) hex = hex.slice(2);
|
|
54
|
+
if (hex.length !== RAW_HEX_LENGTH) return null;
|
|
55
|
+
if (!/^[0-9a-fA-F]+$/.test(hex)) return null;
|
|
56
|
+
const address = new Uint8Array(32);
|
|
57
|
+
for (let i = 0; i < 32; i++) address[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
58
|
+
return {
|
|
59
|
+
workchainId,
|
|
60
|
+
address,
|
|
61
|
+
tag: null
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function tryParseTonAddress(s) {
|
|
65
|
+
if (s.includes(":")) return parseTonRawAddress(s);
|
|
66
|
+
return parseTonUserFriendlyAddress(s);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
exports.TON_ADDRESS_TAG_BOUNCEABLE_MAINNET = TON_ADDRESS_TAG_BOUNCEABLE_MAINNET;
|
|
71
|
+
exports.TON_ADDRESS_TAG_NON_BOUNCEABLE_MAINNET = TON_ADDRESS_TAG_NON_BOUNCEABLE_MAINNET;
|
|
72
|
+
exports.TON_WORKCHAIN_BASECHAIN = TON_WORKCHAIN_BASECHAIN;
|
|
73
|
+
exports.TON_WORKCHAIN_MASTERCHAIN = TON_WORKCHAIN_MASTERCHAIN;
|
|
74
|
+
exports.tryParseTonAddress = tryParseTonAddress;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { base64urlnopad } from "@scure/base";
|
|
2
|
+
|
|
3
|
+
//#region src/lib/ton-address.ts
|
|
4
|
+
/**
|
|
5
|
+
* Tag byte for user-friendly TON addresses. Bit 7 sets testnet, bit 6 sets
|
|
6
|
+
* non-bounceable. See https://docs.ton.org/learn/overviews/addresses#user-friendly-address
|
|
7
|
+
*/
|
|
8
|
+
const TON_ADDRESS_TAG_BOUNCEABLE_MAINNET = 17;
|
|
9
|
+
const TON_ADDRESS_TAG_NON_BOUNCEABLE_MAINNET = 81;
|
|
10
|
+
/**
|
|
11
|
+
* Real TON only uses these two workchains. Other values parse fine but no
|
|
12
|
+
* wallet emits them, so the validator treats them as typos.
|
|
13
|
+
*/
|
|
14
|
+
const TON_WORKCHAIN_BASECHAIN = 0;
|
|
15
|
+
const TON_WORKCHAIN_MASTERCHAIN = -1;
|
|
16
|
+
const TON_USER_FRIENDLY_LENGTH = 36;
|
|
17
|
+
function crc16ccitt(data) {
|
|
18
|
+
let crc = 0;
|
|
19
|
+
for (const byte of data) {
|
|
20
|
+
crc ^= byte << 8;
|
|
21
|
+
for (let i = 0; i < 8; i++) crc = crc & 32768 ? crc << 1 ^ 4129 : crc << 1;
|
|
22
|
+
crc &= 65535;
|
|
23
|
+
}
|
|
24
|
+
return [crc >> 8 & 255, crc & 255];
|
|
25
|
+
}
|
|
26
|
+
function parseTonUserFriendlyAddress(s) {
|
|
27
|
+
const normalized = s.replace(/\+/g, "-").replace(/\//g, "_");
|
|
28
|
+
let data;
|
|
29
|
+
try {
|
|
30
|
+
data = base64urlnopad.decode(normalized);
|
|
31
|
+
} catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
if (data.length !== TON_USER_FRIENDLY_LENGTH) return null;
|
|
35
|
+
const [hi, lo] = crc16ccitt(data.subarray(0, 34));
|
|
36
|
+
if (data[34] !== hi || data[35] !== lo) return null;
|
|
37
|
+
const tag = data[0];
|
|
38
|
+
const wcByte = data[1];
|
|
39
|
+
return {
|
|
40
|
+
tag,
|
|
41
|
+
workchainId: wcByte > 127 ? wcByte - 256 : wcByte,
|
|
42
|
+
address: data.slice(2, 34)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const RAW_HEX_LENGTH = 64;
|
|
46
|
+
function parseTonRawAddress(s) {
|
|
47
|
+
const parts = s.split(":");
|
|
48
|
+
if (parts.length !== 2) return null;
|
|
49
|
+
const workchainId = parseInt(parts[0], 10);
|
|
50
|
+
if (Number.isNaN(workchainId)) return null;
|
|
51
|
+
let hex$1 = parts[1];
|
|
52
|
+
if (hex$1.startsWith("0x")) hex$1 = hex$1.slice(2);
|
|
53
|
+
if (hex$1.length !== RAW_HEX_LENGTH) return null;
|
|
54
|
+
if (!/^[0-9a-fA-F]+$/.test(hex$1)) return null;
|
|
55
|
+
const address = new Uint8Array(32);
|
|
56
|
+
for (let i = 0; i < 32; i++) address[i] = parseInt(hex$1.slice(i * 2, i * 2 + 2), 16);
|
|
57
|
+
return {
|
|
58
|
+
workchainId,
|
|
59
|
+
address,
|
|
60
|
+
tag: null
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function tryParseTonAddress(s) {
|
|
64
|
+
if (s.includes(":")) return parseTonRawAddress(s);
|
|
65
|
+
return parseTonUserFriendlyAddress(s);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
export { TON_ADDRESS_TAG_BOUNCEABLE_MAINNET, TON_ADDRESS_TAG_NON_BOUNCEABLE_MAINNET, TON_WORKCHAIN_BASECHAIN, TON_WORKCHAIN_MASTERCHAIN, tryParseTonAddress };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
2
|
const require_caip2 = require('./caip2.cjs');
|
|
3
|
+
const require_ton_address = require('./ton-address.cjs');
|
|
3
4
|
let _defuse_protocol_internal_utils = require("@defuse-protocol/internal-utils");
|
|
4
5
|
let viem = require("viem");
|
|
5
6
|
let _noble_hashes_sha2 = require("@noble/hashes/sha2");
|
|
@@ -244,26 +245,11 @@ function validateTronHexAddress(address) {
|
|
|
244
245
|
return false;
|
|
245
246
|
}
|
|
246
247
|
}
|
|
247
|
-
function crc16ccitt(data) {
|
|
248
|
-
let crc = 0;
|
|
249
|
-
for (const byte of data) {
|
|
250
|
-
crc ^= byte << 8;
|
|
251
|
-
for (let i = 0; i < 8; i++) crc = crc & 32768 ? crc << 1 ^ 4129 : crc << 1;
|
|
252
|
-
crc &= 65535;
|
|
253
|
-
}
|
|
254
|
-
return [crc >> 8 & 255, crc & 255];
|
|
255
|
-
}
|
|
256
248
|
function validateTonAddress(address) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (tag !== 17 && tag !== 81) return false;
|
|
262
|
-
const [hi, lo] = crc16ccitt(data.subarray(0, 34));
|
|
263
|
-
return data[34] === hi && data[35] === lo;
|
|
264
|
-
} catch {
|
|
265
|
-
return false;
|
|
266
|
-
}
|
|
249
|
+
const parsed = require_ton_address.tryParseTonAddress(address);
|
|
250
|
+
if (parsed === null) return false;
|
|
251
|
+
if (parsed.workchainId !== require_ton_address.TON_WORKCHAIN_BASECHAIN && parsed.workchainId !== require_ton_address.TON_WORKCHAIN_MASTERCHAIN) return false;
|
|
252
|
+
return parsed.tag === null || parsed.tag === require_ton_address.TON_ADDRESS_TAG_BOUNCEABLE_MAINNET || parsed.tag === require_ton_address.TON_ADDRESS_TAG_NON_BOUNCEABLE_MAINNET;
|
|
267
253
|
}
|
|
268
254
|
function validateSuiAddress(address) {
|
|
269
255
|
return /^(?:0x)?[a-fA-F0-9]{64}$/.test(address);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Chains } from "./caip2.js";
|
|
2
|
+
import { TON_ADDRESS_TAG_BOUNCEABLE_MAINNET, TON_ADDRESS_TAG_NON_BOUNCEABLE_MAINNET, TON_WORKCHAIN_BASECHAIN, TON_WORKCHAIN_MASTERCHAIN, tryParseTonAddress } from "./ton-address.js";
|
|
2
3
|
import { utils } from "@defuse-protocol/internal-utils";
|
|
3
4
|
import { isAddress } from "viem";
|
|
4
5
|
import { sha256 } from "@noble/hashes/sha2";
|
|
5
|
-
import { base58,
|
|
6
|
+
import { base58, bech32, bech32m, hex } from "@scure/base";
|
|
6
7
|
import { PublicKey } from "@solana/web3.js";
|
|
7
8
|
import { isValidClassicAddress, isValidXAddress } from "ripple-address-codec";
|
|
8
9
|
|
|
@@ -243,26 +244,11 @@ function validateTronHexAddress(address) {
|
|
|
243
244
|
return false;
|
|
244
245
|
}
|
|
245
246
|
}
|
|
246
|
-
function crc16ccitt(data) {
|
|
247
|
-
let crc = 0;
|
|
248
|
-
for (const byte of data) {
|
|
249
|
-
crc ^= byte << 8;
|
|
250
|
-
for (let i = 0; i < 8; i++) crc = crc & 32768 ? crc << 1 ^ 4129 : crc << 1;
|
|
251
|
-
crc &= 65535;
|
|
252
|
-
}
|
|
253
|
-
return [crc >> 8 & 255, crc & 255];
|
|
254
|
-
}
|
|
255
247
|
function validateTonAddress(address) {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if (tag !== 17 && tag !== 81) return false;
|
|
261
|
-
const [hi, lo] = crc16ccitt(data.subarray(0, 34));
|
|
262
|
-
return data[34] === hi && data[35] === lo;
|
|
263
|
-
} catch {
|
|
264
|
-
return false;
|
|
265
|
-
}
|
|
248
|
+
const parsed = tryParseTonAddress(address);
|
|
249
|
+
if (parsed === null) return false;
|
|
250
|
+
if (parsed.workchainId !== TON_WORKCHAIN_BASECHAIN && parsed.workchainId !== TON_WORKCHAIN_MASTERCHAIN) return false;
|
|
251
|
+
return parsed.tag === null || parsed.tag === TON_ADDRESS_TAG_BOUNCEABLE_MAINNET || parsed.tag === TON_ADDRESS_TAG_NON_BOUNCEABLE_MAINNET;
|
|
266
252
|
}
|
|
267
253
|
function validateSuiAddress(address) {
|
|
268
254
|
return /^(?:0x)?[a-fA-F0-9]{64}$/.test(address);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defuse-protocol/intents-sdk",
|
|
3
|
-
"version": "0.64.
|
|
3
|
+
"version": "0.64.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"@defuse-protocol/internal-utils": "0.32.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
+
"@ton/core": "^0.60.0",
|
|
56
57
|
"tsdown": "0.19.0"
|
|
57
58
|
},
|
|
58
59
|
"scripts": {
|