@defuse-protocol/intents-sdk 0.63.2 → 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.
@@ -39,6 +39,7 @@ const caip2Mapping = {
39
39
  [require_caip2.Chains.Tron]: "tron:mainnet",
40
40
  [require_caip2.Chains.Sui]: "sui:mainnet",
41
41
  [require_caip2.Chains.Aptos]: "aptos:mainnet",
42
+ [require_caip2.Chains.Movement]: "movement:mainnet",
42
43
  [require_caip2.Chains.Cardano]: "cardano:mainnet",
43
44
  [require_caip2.Chains.Litecoin]: "ltc:mainnet",
44
45
  [require_caip2.Chains.Starknet]: "starknet:mainnet",
@@ -65,6 +66,7 @@ const tokenPrefixMapping = {
65
66
  tron: require_caip2.Chains.Tron,
66
67
  sui: require_caip2.Chains.Sui,
67
68
  aptos: require_caip2.Chains.Aptos,
69
+ movement: require_caip2.Chains.Movement,
68
70
  cardano: require_caip2.Chains.Cardano,
69
71
  ltc: require_caip2.Chains.Litecoin,
70
72
  starknet: require_caip2.Chains.Starknet,
@@ -38,6 +38,7 @@ const caip2Mapping = {
38
38
  [Chains.Tron]: "tron:mainnet",
39
39
  [Chains.Sui]: "sui:mainnet",
40
40
  [Chains.Aptos]: "aptos:mainnet",
41
+ [Chains.Movement]: "movement:mainnet",
41
42
  [Chains.Cardano]: "cardano:mainnet",
42
43
  [Chains.Litecoin]: "ltc:mainnet",
43
44
  [Chains.Starknet]: "starknet:mainnet",
@@ -64,6 +65,7 @@ const tokenPrefixMapping = {
64
65
  tron: Chains.Tron,
65
66
  sui: Chains.Sui,
66
67
  aptos: Chains.Aptos,
68
+ movement: Chains.Movement,
67
69
  cardano: Chains.Cardano,
68
70
  ltc: Chains.Litecoin,
69
71
  starknet: Chains.Starknet,
@@ -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 parts = addressString.split(":");
26
- if (parts.length !== 2) throw new Error(`Invalid TON address format: ${addressString}. Expected "workchain:address_hex"`);
27
- const workchainId = parseInt(parts[0], 10);
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 parts = addressString.split(":");
25
- if (parts.length !== 2) throw new Error(`Invalid TON address format: ${addressString}. Expected "workchain:address_hex"`);
26
- const workchainId = parseInt(parts[0], 10);
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
@@ -31,6 +31,7 @@ const Chains = {
31
31
  TON: "tvm:-239",
32
32
  Sui: "sui:mainnet",
33
33
  Aptos: "aptos:mainnet",
34
+ Movement: "move-mvmt:126",
34
35
  Stellar: "stellar:pubnet",
35
36
  Cardano: "cip34:1-764824073",
36
37
  Starknet: "starknet:SN_MAIN",
@@ -28,6 +28,7 @@ declare const Chains: {
28
28
  readonly TON: "tvm:-239";
29
29
  readonly Sui: "sui:mainnet";
30
30
  readonly Aptos: "aptos:mainnet";
31
+ readonly Movement: "move-mvmt:126";
31
32
  readonly Stellar: "stellar:pubnet";
32
33
  readonly Cardano: "cip34:1-764824073";
33
34
  readonly Starknet: "starknet:SN_MAIN";
@@ -28,6 +28,7 @@ declare const Chains: {
28
28
  readonly TON: "tvm:-239";
29
29
  readonly Sui: "sui:mainnet";
30
30
  readonly Aptos: "aptos:mainnet";
31
+ readonly Movement: "move-mvmt:126";
31
32
  readonly Stellar: "stellar:pubnet";
32
33
  readonly Cardano: "cip34:1-764824073";
33
34
  readonly Starknet: "starknet:SN_MAIN";
@@ -30,6 +30,7 @@ const Chains = {
30
30
  TON: "tvm:-239",
31
31
  Sui: "sui:mainnet",
32
32
  Aptos: "aptos:mainnet",
33
+ Movement: "move-mvmt:126",
33
34
  Stellar: "stellar:pubnet",
34
35
  Cardano: "cip34:1-764824073",
35
36
  Starknet: "starknet:SN_MAIN",
@@ -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");
@@ -31,6 +32,7 @@ function validateAddress(address, blockchain) {
31
32
  case require_caip2.Chains.Sui: return validateSuiAddress(address);
32
33
  case require_caip2.Chains.Stellar: return validateStellarAddress(address);
33
34
  case require_caip2.Chains.Aptos: return validateAptosAddress(address);
35
+ case require_caip2.Chains.Movement: return validateMovementAddress(address);
34
36
  case require_caip2.Chains.Cardano: return validateCardanoAddress(address);
35
37
  case require_caip2.Chains.Starknet: return validateStarknetAddress(address);
36
38
  case require_caip2.Chains.Ethereum:
@@ -243,26 +245,11 @@ function validateTronHexAddress(address) {
243
245
  return false;
244
246
  }
245
247
  }
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
248
  function validateTonAddress(address) {
256
- try {
257
- const data = _scure_base.base64urlnopad.decode(address);
258
- if (data.length !== 36) return false;
259
- const tag = data[0];
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
- }
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;
266
253
  }
267
254
  function validateSuiAddress(address) {
268
255
  return /^(?:0x)?[a-fA-F0-9]{64}$/.test(address);
@@ -273,6 +260,15 @@ function validateStellarAddress(address) {
273
260
  function validateAptosAddress(address) {
274
261
  return /^0x[a-fA-F0-9]{64}$/.test(address);
275
262
  }
263
+ function validateMovementAddress(address) {
264
+ let parsedAddress = address;
265
+ if (address.startsWith("0x")) parsedAddress = address.slice(2);
266
+ if (parsedAddress.length === 0 || parsedAddress.length > 64) return false;
267
+ if (!/^[a-fA-F0-9]+$/.test(parsedAddress)) return false;
268
+ if (parsedAddress.length >= 60) return true;
269
+ const paddedAddress = parsedAddress.padStart(64, "0");
270
+ return /^0{63}[0-9a-fA-F]$/.test(paddedAddress);
271
+ }
276
272
  /**
277
273
  * Validates Cardano mainnet addresses (Base + Enterprise)
278
274
  * Returns true if valid, false if invalid
@@ -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, base64urlnopad, bech32, bech32m, hex } from "@scure/base";
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
 
@@ -30,6 +31,7 @@ function validateAddress(address, blockchain) {
30
31
  case Chains.Sui: return validateSuiAddress(address);
31
32
  case Chains.Stellar: return validateStellarAddress(address);
32
33
  case Chains.Aptos: return validateAptosAddress(address);
34
+ case Chains.Movement: return validateMovementAddress(address);
33
35
  case Chains.Cardano: return validateCardanoAddress(address);
34
36
  case Chains.Starknet: return validateStarknetAddress(address);
35
37
  case Chains.Ethereum:
@@ -242,26 +244,11 @@ function validateTronHexAddress(address) {
242
244
  return false;
243
245
  }
244
246
  }
245
- function crc16ccitt(data) {
246
- let crc = 0;
247
- for (const byte of data) {
248
- crc ^= byte << 8;
249
- for (let i = 0; i < 8; i++) crc = crc & 32768 ? crc << 1 ^ 4129 : crc << 1;
250
- crc &= 65535;
251
- }
252
- return [crc >> 8 & 255, crc & 255];
253
- }
254
247
  function validateTonAddress(address) {
255
- try {
256
- const data = base64urlnopad.decode(address);
257
- if (data.length !== 36) return false;
258
- const tag = data[0];
259
- if (tag !== 17 && tag !== 81) return false;
260
- const [hi, lo] = crc16ccitt(data.subarray(0, 34));
261
- return data[34] === hi && data[35] === lo;
262
- } catch {
263
- return false;
264
- }
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;
265
252
  }
266
253
  function validateSuiAddress(address) {
267
254
  return /^(?:0x)?[a-fA-F0-9]{64}$/.test(address);
@@ -272,6 +259,15 @@ function validateStellarAddress(address) {
272
259
  function validateAptosAddress(address) {
273
260
  return /^0x[a-fA-F0-9]{64}$/.test(address);
274
261
  }
262
+ function validateMovementAddress(address) {
263
+ let parsedAddress = address;
264
+ if (address.startsWith("0x")) parsedAddress = address.slice(2);
265
+ if (parsedAddress.length === 0 || parsedAddress.length > 64) return false;
266
+ if (!/^[a-fA-F0-9]+$/.test(parsedAddress)) return false;
267
+ if (parsedAddress.length >= 60) return true;
268
+ const paddedAddress = parsedAddress.padStart(64, "0");
269
+ return /^0{63}[0-9a-fA-F]$/.test(paddedAddress);
270
+ }
275
271
  /**
276
272
  * Validates Cardano mainnet addresses (Base + Enterprise)
277
273
  * Returns true if valid, false if invalid
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defuse-protocol/intents-sdk",
3
- "version": "0.63.2",
3
+ "version": "0.64.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "repository": {
@@ -50,9 +50,10 @@
50
50
  "valibot": "^1.0.0",
51
51
  "viem": "^2.0.0",
52
52
  "@defuse-protocol/contract-types": "0.6.4",
53
- "@defuse-protocol/internal-utils": "0.31.2"
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": {