@multiversx/sdk-dapp-liquidity 2.2.0 → 2.3.0-alpha.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/helpers/assertConfirmRateData.d.ts +19 -0
- package/helpers/assertConfirmRateData.js +2 -0
- package/helpers/assertConfirmRateData.mjs +29 -0
- package/helpers/isValidAddressForChainType.js +1 -1
- package/helpers/isValidAddressForChainType.mjs +28 -16
- package/helpers/tests/assertConfirmRateData.spec.d.ts +1 -0
- package/helpers/tests/assertConfirmRateData.spec.js +2 -0
- package/helpers/tests/assertConfirmRateData.spec.mjs +77 -0
- package/helpers/tests/isValidAddressForChainType.spec.js +1 -1
- package/helpers/tests/isValidAddressForChainType.spec.mjs +49 -15
- package/package.json +1 -6
- package/reactjs/adapters/SuiAdapter.js +1 -1
- package/reactjs/adapters/SuiAdapter.mjs +91 -88
- package/reactjs/components/BridgeForm/Deposit.js +1 -1
- package/reactjs/components/BridgeForm/Deposit.mjs +250 -247
- package/reactjs/components/BridgeForm/Transfer.js +1 -1
- package/reactjs/components/BridgeForm/Transfer.mjs +228 -225
- package/reactjs/hooks/useBridgeFormik.d.ts +1 -0
- package/reactjs/hooks/useBridgeFormik.js +1 -1
- package/reactjs/hooks/useBridgeFormik.mjs +97 -84
- package/reactjs/hooks/useNamespaceAddress.d.ts +19 -0
- package/reactjs/hooks/useNamespaceAddress.js +2 -0
- package/reactjs/hooks/useNamespaceAddress.mjs +16 -0
- package/types/errors.d.ts +15 -0
- package/types/errors.js +1 -1
- package/types/errors.mjs +12 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ConfirmRateGuardParams {
|
|
2
|
+
nativeAuthToken?: string | null;
|
|
3
|
+
orderId?: string | null;
|
|
4
|
+
fromChainId?: string | null;
|
|
5
|
+
toChainId?: string | null;
|
|
6
|
+
sender?: string | null;
|
|
7
|
+
receiver?: string | null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Asserts that all required data is present before calling confirmRate.
|
|
11
|
+
*
|
|
12
|
+
* Throws {@link ConfirmRateError} for missing system tokens (nativeAuthToken, orderId) —
|
|
13
|
+
* these indicate an unexpected app-state problem and should not be shown verbatim.
|
|
14
|
+
*
|
|
15
|
+
* Throws {@link MissingConfirmRateDataError} for missing form fields (fromChainId,
|
|
16
|
+
* toChainId, sender, receiver) — the message names the field and can be surfaced to the
|
|
17
|
+
* user to explain why the bridge couldn't proceed.
|
|
18
|
+
*/
|
|
19
|
+
export declare function assertConfirmRateData({ nativeAuthToken, orderId, fromChainId, toChainId, sender, receiver }: ConfirmRateGuardParams): void;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("../types/errors.js");function s({nativeAuthToken:e,orderId:n,fromChainId:i,toChainId:t,sender:a,receiver:o}){if(!e)throw new r.ConfirmRateError("Cannot confirm rate. Please reconnect your wallet.");if(!n)throw new r.ConfirmRateError("Cannot confirm rate. Please request a new rate.");if(!i)throw new r.MissingConfirmRateDataError("Missing source chain.");if(!t)throw new r.MissingConfirmRateDataError("Missing destination chain.");if(!a)throw new r.MissingConfirmRateDataError("Missing sender address.");if(!o)throw new r.MissingConfirmRateDataError("Missing destination address")}exports.assertConfirmRateData=s;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ConfirmRateError as e, MissingConfirmRateDataError as n } from "../types/errors.mjs";
|
|
2
|
+
function f({
|
|
3
|
+
nativeAuthToken: r,
|
|
4
|
+
orderId: i,
|
|
5
|
+
fromChainId: t,
|
|
6
|
+
toChainId: o,
|
|
7
|
+
sender: a,
|
|
8
|
+
receiver: s
|
|
9
|
+
}) {
|
|
10
|
+
if (!r)
|
|
11
|
+
throw new e(
|
|
12
|
+
"Cannot confirm rate. Please reconnect your wallet."
|
|
13
|
+
);
|
|
14
|
+
if (!i)
|
|
15
|
+
throw new e(
|
|
16
|
+
"Cannot confirm rate. Please request a new rate."
|
|
17
|
+
);
|
|
18
|
+
if (!t)
|
|
19
|
+
throw new n("Missing source chain.");
|
|
20
|
+
if (!o)
|
|
21
|
+
throw new n("Missing destination chain.");
|
|
22
|
+
if (!a)
|
|
23
|
+
throw new n("Missing sender address.");
|
|
24
|
+
if (!s)
|
|
25
|
+
throw new n("Missing destination address");
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
f as assertConfirmRateData
|
|
29
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
2
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("@solana/web3.js"),n=require("bitcoinjs-lib"),i=require("viem"),t=require("../types/chainType.js"),c=/^erd1[0-9a-z]{58}$/,d=/^0x[0-9a-fA-F]{64}$/,a=new Set(["0x0000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","erd1deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaqtv0gag","1111111111111111111114oLvT2"]),u=e=>{const r=e.toLowerCase();return a.has(r)||a.has(e)},o=(e,r)=>{if(!e||!r||u(e))return!1;try{switch(r){case t.ChainType.evm:return i.isAddress(e);case t.ChainType.mvx:return c.test(e);case t.ChainType.sol:try{return new s.PublicKey(e),!0}catch{return!1}case t.ChainType.sui:return d.test(e);case t.ChainType.btc:try{return n.address.toOutputScript(e,n.networks.bitcoin),!0}catch{return!1}default:return!1}}catch{return!1}};exports.isValidAddressForChainType=o;
|
|
@@ -1,27 +1,39 @@
|
|
|
1
|
-
import { PublicKey as
|
|
2
|
-
import { address as
|
|
1
|
+
import { PublicKey as n } from "@solana/web3.js";
|
|
2
|
+
import { address as o, networks as d } from "bitcoinjs-lib";
|
|
3
3
|
import { isAddress as s } from "viem";
|
|
4
|
-
import { ChainType as
|
|
5
|
-
const
|
|
6
|
-
|
|
4
|
+
import { ChainType as t } from "../types/chainType.mjs";
|
|
5
|
+
const c = /^erd1[0-9a-z]{58}$/, u = /^0x[0-9a-fA-F]{64}$/, a = /* @__PURE__ */ new Set([
|
|
6
|
+
// EVM all-zero (20 bytes)
|
|
7
|
+
"0x0000000000000000000000000000000000000000",
|
|
8
|
+
// Sui all-zero (32 bytes)
|
|
9
|
+
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
10
|
+
// MultiversX dead address
|
|
11
|
+
"erd1deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaqtv0gag",
|
|
12
|
+
// BTC unspendable genesis output (base58 is case-sensitive; keep original case)
|
|
13
|
+
"1111111111111111111114oLvT2"
|
|
14
|
+
]), i = (e) => {
|
|
15
|
+
const r = e.toLowerCase();
|
|
16
|
+
return a.has(r) || a.has(e);
|
|
17
|
+
}, p = (e, r) => {
|
|
18
|
+
if (!e || !r || i(e))
|
|
7
19
|
return !1;
|
|
8
20
|
try {
|
|
9
|
-
switch (
|
|
10
|
-
case
|
|
11
|
-
return s(
|
|
12
|
-
case
|
|
13
|
-
return
|
|
14
|
-
case
|
|
21
|
+
switch (r) {
|
|
22
|
+
case t.evm:
|
|
23
|
+
return s(e);
|
|
24
|
+
case t.mvx:
|
|
25
|
+
return c.test(e);
|
|
26
|
+
case t.sol:
|
|
15
27
|
try {
|
|
16
|
-
return new
|
|
28
|
+
return new n(e), !0;
|
|
17
29
|
} catch {
|
|
18
30
|
return !1;
|
|
19
31
|
}
|
|
20
|
-
case
|
|
21
|
-
return
|
|
22
|
-
case
|
|
32
|
+
case t.sui:
|
|
33
|
+
return u.test(e);
|
|
34
|
+
case t.btc:
|
|
23
35
|
try {
|
|
24
|
-
return
|
|
36
|
+
return o.toOutputScript(e, d.bitcoin), !0;
|
|
25
37
|
} catch {
|
|
26
38
|
return !1;
|
|
27
39
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";const t=require("../../types/errors.js"),r=require("../assertConfirmRateData.js"),e={nativeAuthToken:"valid-token",orderId:"order-123",fromChainId:"1",toChainId:"44",sender:"0x71C7656EC7ab88b098defB751B7401B5f6d8976F",receiver:"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"};describe("assertConfirmRateData",()=>{it("does not throw when all required fields are present",()=>{expect(()=>r.assertConfirmRateData(e)).not.toThrow()}),describe("ConfirmRateError — system token missing",()=>{it("throws ConfirmRateError when nativeAuthToken is missing",()=>{expect(()=>r.assertConfirmRateData({...e,nativeAuthToken:void 0})).toThrow(t.ConfirmRateError)}),it("throws ConfirmRateError when nativeAuthToken is empty string",()=>{expect(()=>r.assertConfirmRateData({...e,nativeAuthToken:""})).toThrow(t.ConfirmRateError)}),it("throws ConfirmRateError when orderId is missing",()=>{expect(()=>r.assertConfirmRateData({...e,orderId:void 0})).toThrow(t.ConfirmRateError)}),it("throws ConfirmRateError when orderId is empty string",()=>{expect(()=>r.assertConfirmRateData({...e,orderId:""})).toThrow(t.ConfirmRateError)})}),describe("MissingConfirmRateDataError — required form field missing",()=>{it("throws MissingConfirmRateDataError when fromChainId is missing",()=>{expect(()=>r.assertConfirmRateData({...e,fromChainId:void 0})).toThrow(t.MissingConfirmRateDataError)}),it("throws MissingConfirmRateDataError when toChainId is missing",()=>{expect(()=>r.assertConfirmRateData({...e,toChainId:void 0})).toThrow(t.MissingConfirmRateDataError)}),it("throws MissingConfirmRateDataError when sender is missing",()=>{expect(()=>r.assertConfirmRateData({...e,sender:void 0})).toThrow(t.MissingConfirmRateDataError)}),it("throws MissingConfirmRateDataError when sender is empty string",()=>{expect(()=>r.assertConfirmRateData({...e,sender:""})).toThrow(t.MissingConfirmRateDataError)}),it("throws MissingConfirmRateDataError when receiver is missing",()=>{expect(()=>r.assertConfirmRateData({...e,receiver:void 0})).toThrow(t.MissingConfirmRateDataError)}),it("throws MissingConfirmRateDataError when receiver is empty string",()=>{expect(()=>r.assertConfirmRateData({...e,receiver:""})).toThrow(t.MissingConfirmRateDataError)}),it("error message names the missing field (fromChainId)",()=>{expect(()=>r.assertConfirmRateData({...e,fromChainId:""})).toThrow(/source chain/i)}),it("error message names the missing field (sender)",()=>{expect(()=>r.assertConfirmRateData({...e,sender:""})).toThrow(/sender/i)})}),describe("error priority — system tokens are checked before form fields",()=>{it("throws ConfirmRateError (not MissingConfirmRateDataError) when both nativeAuthToken and sender are missing",()=>{expect(()=>r.assertConfirmRateData({...e,nativeAuthToken:"",sender:""})).toThrow(t.ConfirmRateError)})})});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ConfirmRateError as t, MissingConfirmRateDataError as i } from "../../types/errors.mjs";
|
|
2
|
+
import { assertConfirmRateData as r } from "../assertConfirmRateData.mjs";
|
|
3
|
+
const e = {
|
|
4
|
+
nativeAuthToken: "valid-token",
|
|
5
|
+
orderId: "order-123",
|
|
6
|
+
fromChainId: "1",
|
|
7
|
+
toChainId: "44",
|
|
8
|
+
sender: "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
|
|
9
|
+
receiver: "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"
|
|
10
|
+
};
|
|
11
|
+
describe("assertConfirmRateData", () => {
|
|
12
|
+
it("does not throw when all required fields are present", () => {
|
|
13
|
+
expect(() => r(e)).not.toThrow();
|
|
14
|
+
}), describe("ConfirmRateError — system token missing", () => {
|
|
15
|
+
it("throws ConfirmRateError when nativeAuthToken is missing", () => {
|
|
16
|
+
expect(
|
|
17
|
+
() => r({ ...e, nativeAuthToken: void 0 })
|
|
18
|
+
).toThrow(t);
|
|
19
|
+
}), it("throws ConfirmRateError when nativeAuthToken is empty string", () => {
|
|
20
|
+
expect(
|
|
21
|
+
() => r({ ...e, nativeAuthToken: "" })
|
|
22
|
+
).toThrow(t);
|
|
23
|
+
}), it("throws ConfirmRateError when orderId is missing", () => {
|
|
24
|
+
expect(
|
|
25
|
+
() => r({ ...e, orderId: void 0 })
|
|
26
|
+
).toThrow(t);
|
|
27
|
+
}), it("throws ConfirmRateError when orderId is empty string", () => {
|
|
28
|
+
expect(
|
|
29
|
+
() => r({ ...e, orderId: "" })
|
|
30
|
+
).toThrow(t);
|
|
31
|
+
});
|
|
32
|
+
}), describe("MissingConfirmRateDataError — required form field missing", () => {
|
|
33
|
+
it("throws MissingConfirmRateDataError when fromChainId is missing", () => {
|
|
34
|
+
expect(
|
|
35
|
+
() => r({ ...e, fromChainId: void 0 })
|
|
36
|
+
).toThrow(i);
|
|
37
|
+
}), it("throws MissingConfirmRateDataError when toChainId is missing", () => {
|
|
38
|
+
expect(
|
|
39
|
+
() => r({ ...e, toChainId: void 0 })
|
|
40
|
+
).toThrow(i);
|
|
41
|
+
}), it("throws MissingConfirmRateDataError when sender is missing", () => {
|
|
42
|
+
expect(
|
|
43
|
+
() => r({ ...e, sender: void 0 })
|
|
44
|
+
).toThrow(i);
|
|
45
|
+
}), it("throws MissingConfirmRateDataError when sender is empty string", () => {
|
|
46
|
+
expect(
|
|
47
|
+
() => r({ ...e, sender: "" })
|
|
48
|
+
).toThrow(i);
|
|
49
|
+
}), it("throws MissingConfirmRateDataError when receiver is missing", () => {
|
|
50
|
+
expect(
|
|
51
|
+
() => r({ ...e, receiver: void 0 })
|
|
52
|
+
).toThrow(i);
|
|
53
|
+
}), it("throws MissingConfirmRateDataError when receiver is empty string", () => {
|
|
54
|
+
expect(
|
|
55
|
+
() => r({ ...e, receiver: "" })
|
|
56
|
+
).toThrow(i);
|
|
57
|
+
}), it("error message names the missing field (fromChainId)", () => {
|
|
58
|
+
expect(
|
|
59
|
+
() => r({ ...e, fromChainId: "" })
|
|
60
|
+
).toThrow(/source chain/i);
|
|
61
|
+
}), it("error message names the missing field (sender)", () => {
|
|
62
|
+
expect(
|
|
63
|
+
() => r({ ...e, sender: "" })
|
|
64
|
+
).toThrow(/sender/i);
|
|
65
|
+
});
|
|
66
|
+
}), describe("error priority — system tokens are checked before form fields", () => {
|
|
67
|
+
it("throws ConfirmRateError (not MissingConfirmRateDataError) when both nativeAuthToken and sender are missing", () => {
|
|
68
|
+
expect(
|
|
69
|
+
() => r({
|
|
70
|
+
...e,
|
|
71
|
+
nativeAuthToken: "",
|
|
72
|
+
sender: ""
|
|
73
|
+
})
|
|
74
|
+
).toThrow(t);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";const a=require("../../types/chainType.js"),e=require("../isValidAddressForChainType.js");describe("isValidAddressForChainType",()=>{describe("EVM",()=>{it("accepts a valid checksummed EVM address",()=>{expect(e.isValidAddressForChainType("0x71C7656EC7ab88b098defB751B7401B5f6d8976F",a.ChainType.evm)).toBe(!0)}),it("accepts a lowercase EVM address",()=>{expect(e.isValidAddressForChainType("0x71c7656ec7ab88b098defb751b7401b5f6d8976f",a.ChainType.evm)).toBe(!0)}),it("rejects a non-EVM string",()=>{expect(e.isValidAddressForChainType("not-an-address",a.ChainType.evm)).toBe(!1)})}),describe("MVX",()=>{it("accepts a valid erd1 address",()=>{expect(e.isValidAddressForChainType("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx",a.ChainType.mvx)).toBe(!0)}),it("rejects an EVM address for MVX",()=>{expect(e.isValidAddressForChainType("0x71C7656EC7ab88b098defB751B7401B5f6d8976F",a.ChainType.mvx)).toBe(!1)})}),describe("Solana",()=>{it("accepts a valid base58 Solana address",()=>{expect(e.isValidAddressForChainType("9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",a.ChainType.sol)).toBe(!0)}),it("rejects an invalid Solana address",()=>{expect(e.isValidAddressForChainType("notasoladdr",a.ChainType.sol)).toBe(!1)})}),describe("Sui",()=>{it("accepts a valid Sui address (0x + 64 hex chars)",()=>{expect(e.isValidAddressForChainType("0x"+"a".repeat(64),a.ChainType.sui)).toBe(!0)}),it("rejects an EVM-shaped address (0x + 40 hex chars) for Sui — the reported bug",()=>{expect(e.isValidAddressForChainType("0x2566c27aaafa46818c4d91fd4ab88137d26764fd",a.ChainType.sui)).toBe(!1)}),it("rejects a non-hex string for Sui",()=>{expect(e.isValidAddressForChainType("notasuiaddr",a.ChainType.sui)).toBe(!1)})}),describe("BTC",()=>{it("accepts a valid bech32 mainnet address",()=>{expect(e.isValidAddressForChainType("bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",a.ChainType.btc)).toBe(!0)}),it("accepts a valid legacy P2PKH address",()=>{expect(e.isValidAddressForChainType("1BoatSLRHtKNngkdXEeobR76b53LETtpyT",a.ChainType.btc)).toBe(!0)}),it("rejects a garbage string for BTC",()=>{expect(e.isValidAddressForChainType("notabtcaddr",a.ChainType.btc)).toBe(!1)})}),describe("edge cases",()=>{it("returns true for undefined address (no constraint)",()=>{expect(e.isValidAddressForChainType(void 0,a.ChainType.evm)).toBe(!1)}),it("returns true for undefined chainType (no constraint)",()=>{expect(e.isValidAddressForChainType("0x71C7656EC7ab88b098defB751B7401B5f6d8976F",void 0)).toBe(!1)})})});
|
|
2
|
+
"use strict";const a=require("../../types/chainType.js"),e=require("../isValidAddressForChainType.js");describe("isValidAddressForChainType",()=>{describe("EVM",()=>{it("accepts a valid checksummed EVM address",()=>{expect(e.isValidAddressForChainType("0x71C7656EC7ab88b098defB751B7401B5f6d8976F",a.ChainType.evm)).toBe(!0)}),it("accepts a lowercase EVM address",()=>{expect(e.isValidAddressForChainType("0x71c7656ec7ab88b098defb751b7401b5f6d8976f",a.ChainType.evm)).toBe(!0)}),it("rejects a non-EVM string",()=>{expect(e.isValidAddressForChainType("not-an-address",a.ChainType.evm)).toBe(!1)})}),describe("MVX",()=>{it("accepts a valid erd1 address",()=>{expect(e.isValidAddressForChainType("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx",a.ChainType.mvx)).toBe(!0)}),it("rejects an EVM address for MVX",()=>{expect(e.isValidAddressForChainType("0x71C7656EC7ab88b098defB751B7401B5f6d8976F",a.ChainType.mvx)).toBe(!1)})}),describe("Solana",()=>{it("accepts a valid base58 Solana address",()=>{expect(e.isValidAddressForChainType("9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",a.ChainType.sol)).toBe(!0)}),it("rejects an invalid Solana address",()=>{expect(e.isValidAddressForChainType("notasoladdr",a.ChainType.sol)).toBe(!1)})}),describe("Sui",()=>{it("accepts a valid Sui address (0x + 64 hex chars)",()=>{expect(e.isValidAddressForChainType("0x"+"a".repeat(64),a.ChainType.sui)).toBe(!0)}),it("rejects an EVM-shaped address (0x + 40 hex chars) for Sui — the reported bug",()=>{expect(e.isValidAddressForChainType("0x2566c27aaafa46818c4d91fd4ab88137d26764fd",a.ChainType.sui)).toBe(!1)}),it("rejects a non-hex string for Sui",()=>{expect(e.isValidAddressForChainType("notasuiaddr",a.ChainType.sui)).toBe(!1)})}),describe("BTC",()=>{it("accepts a valid bech32 mainnet address",()=>{expect(e.isValidAddressForChainType("bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",a.ChainType.btc)).toBe(!0)}),it("accepts a valid legacy P2PKH address",()=>{expect(e.isValidAddressForChainType("1BoatSLRHtKNngkdXEeobR76b53LETtpyT",a.ChainType.btc)).toBe(!0)}),it("rejects a garbage string for BTC",()=>{expect(e.isValidAddressForChainType("notabtcaddr",a.ChainType.btc)).toBe(!1)})}),describe("edge cases",()=>{it("returns true for undefined address (no constraint)",()=>{expect(e.isValidAddressForChainType(void 0,a.ChainType.evm)).toBe(!1)}),it("returns true for undefined chainType (no constraint)",()=>{expect(e.isValidAddressForChainType("0x71C7656EC7ab88b098defB751B7401B5f6d8976F",void 0)).toBe(!1)})}),describe("burn / null addresses",()=>{it("rejects EVM all-zero burn address",()=>{expect(e.isValidAddressForChainType("0x0000000000000000000000000000000000000000",a.ChainType.evm)).toBe(!1)}),it("rejects Sui all-zero burn address",()=>{expect(e.isValidAddressForChainType("0x0000000000000000000000000000000000000000000000000000000000000000",a.ChainType.sui)).toBe(!1)}),it("rejects MultiversX dead address",()=>{expect(e.isValidAddressForChainType("erd1deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaqtv0gag",a.ChainType.mvx)).toBe(!1)}),it("rejects BTC unspendable genesis burn address",()=>{expect(e.isValidAddressForChainType("1111111111111111111114oLvT2",a.ChainType.btc)).toBe(!1)}),it("rejects EVM all-zero burn address regardless of case",()=>{expect(e.isValidAddressForChainType("0X0000000000000000000000000000000000000000".toLowerCase(),a.ChainType.evm)).toBe(!1)})})});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChainType as
|
|
1
|
+
import { ChainType as a } from "../../types/chainType.mjs";
|
|
2
2
|
import { isValidAddressForChainType as e } from "../isValidAddressForChainType.mjs";
|
|
3
3
|
describe("isValidAddressForChainType", () => {
|
|
4
4
|
describe("EVM", () => {
|
|
@@ -6,18 +6,18 @@ describe("isValidAddressForChainType", () => {
|
|
|
6
6
|
expect(
|
|
7
7
|
e(
|
|
8
8
|
"0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
|
|
9
|
-
|
|
9
|
+
a.evm
|
|
10
10
|
)
|
|
11
11
|
).toBe(!0);
|
|
12
12
|
}), it("accepts a lowercase EVM address", () => {
|
|
13
13
|
expect(
|
|
14
14
|
e(
|
|
15
15
|
"0x71c7656ec7ab88b098defb751b7401b5f6d8976f",
|
|
16
|
-
|
|
16
|
+
a.evm
|
|
17
17
|
)
|
|
18
18
|
).toBe(!0);
|
|
19
19
|
}), it("rejects a non-EVM string", () => {
|
|
20
|
-
expect(e("not-an-address",
|
|
20
|
+
expect(e("not-an-address", a.evm)).toBe(
|
|
21
21
|
!1
|
|
22
22
|
);
|
|
23
23
|
});
|
|
@@ -26,14 +26,14 @@ describe("isValidAddressForChainType", () => {
|
|
|
26
26
|
expect(
|
|
27
27
|
e(
|
|
28
28
|
"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx",
|
|
29
|
-
|
|
29
|
+
a.mvx
|
|
30
30
|
)
|
|
31
31
|
).toBe(!0);
|
|
32
32
|
}), it("rejects an EVM address for MVX", () => {
|
|
33
33
|
expect(
|
|
34
34
|
e(
|
|
35
35
|
"0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
|
|
36
|
-
|
|
36
|
+
a.mvx
|
|
37
37
|
)
|
|
38
38
|
).toBe(!1);
|
|
39
39
|
});
|
|
@@ -42,28 +42,28 @@ describe("isValidAddressForChainType", () => {
|
|
|
42
42
|
expect(
|
|
43
43
|
e(
|
|
44
44
|
"9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
|
|
45
|
-
|
|
45
|
+
a.sol
|
|
46
46
|
)
|
|
47
47
|
).toBe(!0);
|
|
48
48
|
}), it("rejects an invalid Solana address", () => {
|
|
49
|
-
expect(e("notasoladdr",
|
|
49
|
+
expect(e("notasoladdr", a.sol)).toBe(
|
|
50
50
|
!1
|
|
51
51
|
);
|
|
52
52
|
});
|
|
53
53
|
}), describe("Sui", () => {
|
|
54
54
|
it("accepts a valid Sui address (0x + 64 hex chars)", () => {
|
|
55
55
|
expect(
|
|
56
|
-
e("0x" + "a".repeat(64),
|
|
56
|
+
e("0x" + "a".repeat(64), a.sui)
|
|
57
57
|
).toBe(!0);
|
|
58
58
|
}), it("rejects an EVM-shaped address (0x + 40 hex chars) for Sui — the reported bug", () => {
|
|
59
59
|
expect(
|
|
60
60
|
e(
|
|
61
61
|
"0x2566c27aaafa46818c4d91fd4ab88137d26764fd",
|
|
62
|
-
|
|
62
|
+
a.sui
|
|
63
63
|
)
|
|
64
64
|
).toBe(!1);
|
|
65
65
|
}), it("rejects a non-hex string for Sui", () => {
|
|
66
|
-
expect(e("notasuiaddr",
|
|
66
|
+
expect(e("notasuiaddr", a.sui)).toBe(
|
|
67
67
|
!1
|
|
68
68
|
);
|
|
69
69
|
});
|
|
@@ -72,24 +72,24 @@ describe("isValidAddressForChainType", () => {
|
|
|
72
72
|
expect(
|
|
73
73
|
e(
|
|
74
74
|
"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
|
|
75
|
-
|
|
75
|
+
a.btc
|
|
76
76
|
)
|
|
77
77
|
).toBe(!0);
|
|
78
78
|
}), it("accepts a valid legacy P2PKH address", () => {
|
|
79
79
|
expect(
|
|
80
80
|
e(
|
|
81
81
|
"1BoatSLRHtKNngkdXEeobR76b53LETtpyT",
|
|
82
|
-
|
|
82
|
+
a.btc
|
|
83
83
|
)
|
|
84
84
|
).toBe(!0);
|
|
85
85
|
}), it("rejects a garbage string for BTC", () => {
|
|
86
|
-
expect(e("notabtcaddr",
|
|
86
|
+
expect(e("notabtcaddr", a.btc)).toBe(
|
|
87
87
|
!1
|
|
88
88
|
);
|
|
89
89
|
});
|
|
90
90
|
}), describe("edge cases", () => {
|
|
91
91
|
it("returns true for undefined address (no constraint)", () => {
|
|
92
|
-
expect(e(void 0,
|
|
92
|
+
expect(e(void 0, a.evm)).toBe(!1);
|
|
93
93
|
}), it("returns true for undefined chainType (no constraint)", () => {
|
|
94
94
|
expect(
|
|
95
95
|
e(
|
|
@@ -98,5 +98,39 @@ describe("isValidAddressForChainType", () => {
|
|
|
98
98
|
)
|
|
99
99
|
).toBe(!1);
|
|
100
100
|
});
|
|
101
|
+
}), describe("burn / null addresses", () => {
|
|
102
|
+
it("rejects EVM all-zero burn address", () => {
|
|
103
|
+
expect(
|
|
104
|
+
e(
|
|
105
|
+
"0x0000000000000000000000000000000000000000",
|
|
106
|
+
a.evm
|
|
107
|
+
)
|
|
108
|
+
).toBe(!1);
|
|
109
|
+
}), it("rejects Sui all-zero burn address", () => {
|
|
110
|
+
expect(
|
|
111
|
+
e(
|
|
112
|
+
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
113
|
+
a.sui
|
|
114
|
+
)
|
|
115
|
+
).toBe(!1);
|
|
116
|
+
}), it("rejects MultiversX dead address", () => {
|
|
117
|
+
expect(
|
|
118
|
+
e(
|
|
119
|
+
"erd1deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaqtv0gag",
|
|
120
|
+
a.mvx
|
|
121
|
+
)
|
|
122
|
+
).toBe(!1);
|
|
123
|
+
}), it("rejects BTC unspendable genesis burn address", () => {
|
|
124
|
+
expect(
|
|
125
|
+
e("1111111111111111111114oLvT2", a.btc)
|
|
126
|
+
).toBe(!1);
|
|
127
|
+
}), it("rejects EVM all-zero burn address regardless of case", () => {
|
|
128
|
+
expect(
|
|
129
|
+
e(
|
|
130
|
+
"0X0000000000000000000000000000000000000000".toLowerCase(),
|
|
131
|
+
a.evm
|
|
132
|
+
)
|
|
133
|
+
).toBe(!1);
|
|
134
|
+
});
|
|
101
135
|
});
|
|
102
136
|
});
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"author": "MultiversX",
|
|
4
4
|
"description": "A complete toolkit for bridging assets between MultiversX, Ethereum, BNB Chain and Sui",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.3.0-alpha.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git+https://github.com/multiversx/mx-sdk-dapp-liquidity.git"
|
|
@@ -79,11 +79,6 @@
|
|
|
79
79
|
"wagmi": "3.6.14",
|
|
80
80
|
"yup": "1.4.0"
|
|
81
81
|
},
|
|
82
|
-
"pnpm": {
|
|
83
|
-
"overrides": {
|
|
84
|
-
"protobufjs": ">=7.5.5"
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
82
|
"peerDependencies": {
|
|
88
83
|
"@multiversx/sdk-core": ">= 15.x",
|
|
89
84
|
"@wagmi/core": ">= 3.x",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var y=Object.defineProperty;var v=(d,o,t)=>o in d?y(d,o,{enumerable:!0,configurable:!0,writable:!0,value:t}):d[o]=t;var l=(d,o,t)=>v(d,typeof o!="symbol"?o+"":o,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("@reown/appkit-controllers"),g="walletConnect",m=["sui:mainnet","sui:testnet","sui:devnet"];class w extends h.AdapterBlueprint{constructor(t){super({namespace:"sui",adapterType:"sui"});l(this,"sharedWcProvider");l(this,"explicitCaipChainsFromInit");l(this,"expectedSuiAddress");l(this,"suiNetworksFromConfig",[]);this.explicitCaipChainsFromInit=(t==null?void 0:t.explicitCaipChains)??[],this.expectedSuiAddress=t==null?void 0:t.expectedSuiAddress}construct(t){super.construct(t),this.suiNetworksFromConfig=t.networks??[]}pickChainsFromExplicit(t,e){if(t.length===0)return m;if(e!=null){const n=e.toString(),i=t.find(s=>s===`sui:${n}`||s.endsWith(`:${n}`));if(i)return[i]}return t}resolveSuiChainsForConnect(t){const e=this.getCaipNetworks("sui"),n=e.length>0?e:this.suiNetworksFromConfig;if(n.length===0)return this.pickChainsFromExplicit(this.explicitCaipChainsFromInit,t);const i=s=>s.caipNetworkId||`sui:${s.id}`;if(t!=null){const s=n.find(r=>{var c;return((c=r.id)==null?void 0:c.toString())===t.toString()});if(s)return[i(s)]}return n.map(i)}getCaipNetworksForWalletConnectConnector(){return this.suiNetworksFromConfig.length>0?this.suiNetworksFromConfig:(this.explicitCaipChainsFromInit.length>0?this.explicitCaipChainsFromInit:m).map(e=>{const n=e.startsWith("sui:")?e.slice(4):e;return{id:n,chainNamespace:"sui",caipNetworkId:e,name:"Sui",nativeCurrency:{name:"SUI",symbol:"SUI",decimals:9},rpcUrls:{default:{http:[`https://fullnode.${n}.sui.io:443`]}}}})}syncConnectors(){}async setUniversalProvider(t){this.sharedWcProvider=t;const e=new h.WalletConnectConnector({provider:t,namespace:"sui",caipNetworks:this.getCaipNetworksForWalletConnectConnector()});this.addConnector(e),h.WcHelpersUtil.listenWcProvider({universalProvider:t,namespace:"sui",onConnect:n=>this.onConnect(n,g),onDisconnect:()=>this.onDisconnect(g),onAccountsChanged:n=>this.onAccountsChanged(n,g,!1)})}getWcProvider(){if(!this.sharedWcProvider)throw new Error("SuiAdapter: UniversalProvider not ready — setUniversalProvider must run before connect");return this.sharedWcProvider}async connectWalletConnect(t){var r,c;const e=this.getWcProvider();if((c=(r=e.session)==null?void 0:r.namespaces)!=null&&c.sui)return{clientId:await e.client.core.crypto.getClientId()};const n=this.resolveSuiChainsForConnect(t),i=n.length>0?n:m;return await e.connect({optionalNamespaces:{sui:{methods:["sui_signPersonalMessage","sui_signTransaction","sui_signAndExecuteTransaction"],chains:i,events:[]}}}),{clientId:await e.client.core.crypto.getClientId()}}async connect(t){var C,f,p;const e=this.connectors.find(u=>u.id===t.id);if(!e)throw new Error("Sui connector not found");const n=this.getConnection({address:t.address,connectorId:e.id,connections:this.connections,connectors:this.connectors});if(n!=null&&n.account){const u=((C=n.caipNetwork)==null?void 0:C.id)??t.chainId??"mainnet";return this.emit("accountChanged",{address:n.account.address,chainId:u,connector:e}),{id:e.id,address:n.account.address,chainId:u,provider:e.provider,type:e.type}}const i=this.getWcProvider(),r=(f=h.WcHelpersUtil.getWalletConnectAccounts(i,"sui")[0])==null?void 0:f.address;if(!r)throw new Error("No Sui account found after WalletConnect session");if(this.expectedSuiAddress&&r!==this.expectedSuiAddress)throw new Error(`Sui account mismatch: expected ${this.expectedSuiAddress}, got ${r}`);const c=(p=this.getCaipNetworks())==null?void 0:p.find(u=>u.id===t.chainId);this.addConnection({connectorId:e.id,accounts:[{address:r}],caipNetwork:c});const a=t.chainId??(c==null?void 0:c.id)??"mainnet";return this.emit("accountChanged",{address:r,chainId:a,connector:e}),{id:e.id,address:r,chainId:a,provider:e.provider,type:e.type}}async disconnect(t){if(
|
|
2
|
+
"use strict";var y=Object.defineProperty;var v=(d,o,t)=>o in d?y(d,o,{enumerable:!0,configurable:!0,writable:!0,value:t}):d[o]=t;var l=(d,o,t)=>v(d,typeof o!="symbol"?o+"":o,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("@reown/appkit-controllers"),g="walletConnect",m=["sui:mainnet","sui:testnet","sui:devnet"];class w extends h.AdapterBlueprint{constructor(t){super({namespace:"sui",adapterType:"sui"});l(this,"sharedWcProvider");l(this,"explicitCaipChainsFromInit");l(this,"expectedSuiAddress");l(this,"suiNetworksFromConfig",[]);this.explicitCaipChainsFromInit=(t==null?void 0:t.explicitCaipChains)??[],this.expectedSuiAddress=t==null?void 0:t.expectedSuiAddress}construct(t){super.construct(t),this.suiNetworksFromConfig=t.networks??[]}pickChainsFromExplicit(t,e){if(t.length===0)return m;if(e!=null){const n=e.toString(),i=t.find(s=>s===`sui:${n}`||s.endsWith(`:${n}`));if(i)return[i]}return t}resolveSuiChainsForConnect(t){const e=this.getCaipNetworks("sui"),n=e.length>0?e:this.suiNetworksFromConfig;if(n.length===0)return this.pickChainsFromExplicit(this.explicitCaipChainsFromInit,t);const i=s=>s.caipNetworkId||`sui:${s.id}`;if(t!=null){const s=n.find(r=>{var c;return((c=r.id)==null?void 0:c.toString())===t.toString()});if(s)return[i(s)]}return n.map(i)}getCaipNetworksForWalletConnectConnector(){return this.suiNetworksFromConfig.length>0?this.suiNetworksFromConfig:(this.explicitCaipChainsFromInit.length>0?this.explicitCaipChainsFromInit:m).map(e=>{const n=e.startsWith("sui:")?e.slice(4):e;return{id:n,chainNamespace:"sui",caipNetworkId:e,name:"Sui",nativeCurrency:{name:"SUI",symbol:"SUI",decimals:9},rpcUrls:{default:{http:[`https://fullnode.${n}.sui.io:443`]}}}})}syncConnectors(){}async setUniversalProvider(t){this.sharedWcProvider=t;const e=new h.WalletConnectConnector({provider:t,namespace:"sui",caipNetworks:this.getCaipNetworksForWalletConnectConnector()});this.addConnector(e),h.WcHelpersUtil.listenWcProvider({universalProvider:t,namespace:"sui",onConnect:n=>this.onConnect(n,g),onDisconnect:()=>this.onDisconnect(g),onAccountsChanged:n=>this.onAccountsChanged(n,g,!1)})}getWcProvider(){if(!this.sharedWcProvider)throw new Error("SuiAdapter: UniversalProvider not ready — setUniversalProvider must run before connect");return this.sharedWcProvider}async connectWalletConnect(t){var r,c;const e=this.getWcProvider();if((c=(r=e.session)==null?void 0:r.namespaces)!=null&&c.sui)return{clientId:await e.client.core.crypto.getClientId()};const n=this.resolveSuiChainsForConnect(t),i=n.length>0?n:m;return await e.connect({optionalNamespaces:{sui:{methods:["sui_signPersonalMessage","sui_signTransaction","sui_signAndExecuteTransaction"],chains:i,events:[]}}}),{clientId:await e.client.core.crypto.getClientId()}}async connect(t){var C,f,p;const e=this.connectors.find(u=>u.id===t.id);if(!e)throw new Error("Sui connector not found");const n=this.getConnection({address:t.address,connectorId:e.id,connections:this.connections,connectors:this.connectors});if(n!=null&&n.account){const u=((C=n.caipNetwork)==null?void 0:C.id)??t.chainId??"mainnet";return this.emit("accountChanged",{address:n.account.address,chainId:u,connector:e}),{id:e.id,address:n.account.address,chainId:u,provider:e.provider,type:e.type}}const i=this.getWcProvider(),r=(f=h.WcHelpersUtil.getWalletConnectAccounts(i,"sui")[0])==null?void 0:f.address;if(!r)throw new Error("No Sui account found after WalletConnect session");if(this.expectedSuiAddress&&r!==this.expectedSuiAddress)throw new Error(`Sui account mismatch: expected ${this.expectedSuiAddress}, got ${r}`);const c=(p=this.getCaipNetworks())==null?void 0:p.find(u=>u.id===t.chainId);this.addConnection({connectorId:e.id,accounts:[{address:r}],caipNetwork:c});const a=t.chainId??(c==null?void 0:c.id)??"mainnet";return this.emit("accountChanged",{address:r,chainId:a,connector:e}),{id:e.id,address:r,chainId:a,provider:e.provider,type:e.type}}async disconnect(t){var e,n,i;if((i=(n=(e=this.sharedWcProvider)==null?void 0:e.session)==null?void 0:n.namespaces)!=null&&i.sui)try{await this.sharedWcProvider.disconnect()}catch{}if(t!=null&&t.id)this.deleteConnection(t.id);else for(const s of[...this.connections])this.deleteConnection(s.connectorId);return this.connections.length===0?this.emit("disconnect"):this.emitFirstAvailableConnection(),{connections:this.connections}}async getAccounts(t){return this.sharedWcProvider?{accounts:h.WcHelpersUtil.getWalletConnectAccounts(this.sharedWcProvider,"sui").map(n=>({namespace:"sui",address:n.address,type:"eoa"}))}:{accounts:[]}}async getBalance(t){var e,n,i;if(!t.address)return{balance:"0",symbol:"SUI"};try{const s=(e=this.getCaipNetworks())==null?void 0:e.find(p=>p.id===t.chainId),r=`https://fullnode.${s==null?void 0:s.id}.sui.io:443`;if(!r)return{balance:"0",symbol:"SUI"};const a=await(await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"suix_getBalance",params:[t.address,"0x2::sui::SUI"]})})).json(),C=((n=a==null?void 0:a.result)==null?void 0:n.totalBalance)??"0";return{balance:(parseInt(C,10)/1e9).toString(),symbol:((i=s==null?void 0:s.nativeCurrency)==null?void 0:i.symbol)||"SUI"}}catch{return{balance:"0",symbol:"SUI"}}}async switchNetwork(t){await super.switchNetwork(t)}async syncConnection(t){return this.connect({...t,type:""})}async syncConnections({connectToFirstConnector:t,caipNetwork:e}){if(!this.sharedWcProvider)return;const n=h.WcHelpersUtil.getWalletConnectAccounts(this.sharedWcProvider,"sui");n.length>0&&this.addConnection({connectorId:g,accounts:n.map(i=>({address:i.address})),caipNetwork:e}),t&&this.emitFirstAvailableConnection()}getWalletConnectProvider(t){return t.provider}getChainScope(t){if(t!=null&&t.startsWith("sui:"))return t;const e=this.explicitCaipChainsFromInit.find(n=>n.startsWith("sui:"));return e||"sui:mainnet"}async signMessage(t){const e=this.getWcProvider(),n=this.getChainScope();return{signature:(await e.request({method:"sui_signPersonalMessage",params:{message:t.message,address:t.address}},n)).signature}}async sendTransaction(t){var s;const e=this.getWcProvider(),n=this.getChainScope((s=t.caipNetwork)==null?void 0:s.caipNetworkId);return{hash:(await e.request({method:"sui_signAndExecuteTransaction",params:{transaction:t.data,address:t.to}},n)).digest}}async estimateGas(){return{gas:0n}}async writeContract(){return{hash:""}}parseUnits(){return 0n}formatUnits(){return""}async getCapabilities(){return{}}async grantPermissions(){return{}}async revokePermissions(){return"0x"}async walletGetAssets(){return{}}}exports.SuiAdapter=w;
|