@multiversx/sdk-dapp-liquidity 2.0.0-alpha.4 → 2.1.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/assertRateConfirmationMatchesIntent.d.ts +8 -0
- package/helpers/assertRateConfirmationMatchesIntent.js +24 -0
- package/helpers/assertRateConfirmationMatchesIntent.mjs +23 -0
- package/helpers/index.d.ts +2 -0
- package/helpers/index.js +4 -0
- package/helpers/index.mjs +4 -0
- package/helpers/safeImageUrl.d.ts +1 -0
- package/helpers/safeImageUrl.js +24 -0
- package/helpers/safeImageUrl.mjs +23 -0
- package/helpers/serializeTransaction.js +1 -1
- package/helpers/serializeTransaction.mjs +1 -1
- package/helpers/tests/assertRateConfirmationMatchesIntent.spec.d.ts +1 -0
- package/helpers/tests/assertRateConfirmationMatchesIntent.spec.js +64 -0
- package/helpers/tests/assertRateConfirmationMatchesIntent.spec.mjs +62 -0
- package/helpers/tests/safeImageUrl.spec.d.ts +1 -0
- package/helpers/tests/safeImageUrl.spec.js +49 -0
- package/helpers/tests/safeImageUrl.spec.mjs +47 -0
- package/helpers/tests/serializeTransaction.spec.d.ts +1 -0
- package/helpers/tests/serializeTransaction.spec.js +37 -0
- package/helpers/tests/serializeTransaction.spec.mjs +35 -0
- package/index.js +7 -3
- package/index.mjs +10 -6
- package/package.json +14 -9
- package/react.esm-7GsOwMPq.js +11815 -0
- package/react.esm-CU-Iqz8D.mjs +11796 -0
- package/reactjs/adapters/SuiAdapter.d.ts +14 -0
- package/reactjs/adapters/SuiAdapter.js +31 -2
- package/reactjs/adapters/SuiAdapter.mjs +31 -2
- package/reactjs/components/BridgeForm/Deposit.js +9 -7
- package/reactjs/components/BridgeForm/Deposit.mjs +8 -6
- package/reactjs/components/BridgeForm/Transfer.js +8 -6
- package/reactjs/components/BridgeForm/Transfer.mjs +7 -5
- package/reactjs/components/BridgeHistory/BridgeHistory.js +20 -6
- package/reactjs/components/BridgeHistory/BridgeHistory.mjs +20 -6
- package/reactjs/components/Connect/BridgeConnectButton.js +2 -1
- package/reactjs/components/Connect/BridgeConnectButton.mjs +2 -1
- package/reactjs/components/CopyButton/CopyButton.mjs +2 -2
- package/reactjs/components/TokenSelector/components/ChainSelect/components/ChainOptionLabel.js +5 -1
- package/reactjs/components/TokenSelector/components/ChainSelect/components/ChainOptionLabel.mjs +6 -2
- package/reactjs/components/TokenSelector/components/ChainSelect/components/SelectedChainOption.js +5 -1
- package/reactjs/components/TokenSelector/components/ChainSelect/components/SelectedChainOption.mjs +6 -2
- package/reactjs/components/TokenSelector/components/TokenIcon.js +2 -1
- package/reactjs/components/TokenSelector/components/TokenIcon.mjs +2 -1
- package/reactjs/context/Web3AppProvider.js +4 -2
- package/reactjs/context/Web3AppProvider.mjs +6 -4
- package/reactjs/hooks/tests/useGenericSignMessage.spec.d.ts +1 -0
- package/reactjs/hooks/tests/useGenericSignMessage.spec.js +69 -0
- package/reactjs/hooks/tests/useGenericSignMessage.spec.mjs +67 -0
- package/reactjs/hooks/tests/useSignTransaction.spec.d.ts +1 -0
- package/reactjs/hooks/tests/useSignTransaction.spec.js +196 -0
- package/reactjs/hooks/tests/useSignTransaction.spec.mjs +194 -0
- package/reactjs/hooks/useBridgeFormik.js +5 -0
- package/reactjs/hooks/useBridgeFormik.mjs +5 -0
- package/reactjs/hooks/useFetchTokens.js +4 -2
- package/reactjs/hooks/useFetchTokens.mjs +4 -2
- package/reactjs/hooks/useGenericSignMessage.js +23 -3
- package/reactjs/hooks/useGenericSignMessage.mjs +23 -3
- package/reactjs/hooks/useSignTransaction.js +27 -1
- package/reactjs/hooks/useSignTransaction.mjs +28 -2
- package/reactjs/index.js +3 -3
- package/reactjs/index.mjs +6 -6
- package/reactjs/init/init.d.ts +1 -0
- package/reactjs/init/init.js +11 -3
- package/reactjs/init/init.mjs +11 -3
- package/reactjs/queries/index.js +3 -3
- package/reactjs/queries/index.mjs +7 -7
- package/reactjs/queries/useCheckAccount.query.js +1 -1
- package/reactjs/queries/useCheckAccount.query.mjs +1 -1
- package/reactjs/queries/useGetAllTokens.query.js +1 -1
- package/reactjs/queries/useGetAllTokens.query.mjs +1 -1
- package/reactjs/queries/useGetChains.query.js +1 -1
- package/reactjs/queries/useGetChains.query.mjs +1 -1
- package/reactjs/queries/useGetHistory.query.d.ts +1 -1
- package/reactjs/queries/useGetHistory.query.js +10 -9
- package/reactjs/queries/useGetHistory.query.mjs +12 -11
- package/reactjs/queries/useGetMvxTokensBalances.query.d.ts +1 -1
- package/reactjs/queries/useGetMvxTokensBalances.query.js +9 -14
- package/reactjs/queries/useGetMvxTokensBalances.query.mjs +12 -17
- package/reactjs/queries/useGetNonMvxTokensBalances.query.d.ts +1 -1
- package/reactjs/queries/useGetNonMvxTokensBalances.query.js +8 -8
- package/reactjs/queries/useGetNonMvxTokensBalances.query.mjs +11 -11
- package/types/errors.d.ts +3 -0
- package/types/errors.js +10 -0
- package/types/errors.mjs +9 -0
- package/reactjs/hooks/useSignTransaction.d.ts +0 -511
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ServerTransaction } from '../types/transaction';
|
|
2
|
+
|
|
3
|
+
interface ConfirmIntent {
|
|
4
|
+
fromChainId: string;
|
|
5
|
+
sender: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function assertRateConfirmationMatchesIntent(intent: ConfirmIntent, transactions: ServerTransaction[]): void;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const types_errors = require("../types/errors.js");
|
|
5
|
+
function assertRateConfirmationMatchesIntent(intent, transactions) {
|
|
6
|
+
for (const tx of transactions) {
|
|
7
|
+
if (tx.chainID !== void 0 && String(tx.chainID) !== String(intent.fromChainId)) {
|
|
8
|
+
throw new types_errors.RateConfirmationMismatchError(
|
|
9
|
+
`Transaction chainID ${tx.chainID} does not match approved fromChainId ${intent.fromChainId}`
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
if (tx.account !== void 0 && tx.account !== "" && intent.sender !== "" && tx.account.toLowerCase() !== intent.sender.toLowerCase()) {
|
|
13
|
+
throw new types_errors.RateConfirmationMismatchError(
|
|
14
|
+
`Transaction account ${tx.account} does not match approved sender ${intent.sender}`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
if (tx.sender !== void 0 && tx.sender !== "" && intent.sender !== "" && tx.sender.toLowerCase() !== intent.sender.toLowerCase()) {
|
|
18
|
+
throw new types_errors.RateConfirmationMismatchError(
|
|
19
|
+
`Transaction sender ${tx.sender} does not match approved sender ${intent.sender}`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.assertRateConfirmationMatchesIntent = assertRateConfirmationMatchesIntent;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RateConfirmationMismatchError } from "../types/errors.mjs";
|
|
2
|
+
function assertRateConfirmationMatchesIntent(intent, transactions) {
|
|
3
|
+
for (const tx of transactions) {
|
|
4
|
+
if (tx.chainID !== void 0 && String(tx.chainID) !== String(intent.fromChainId)) {
|
|
5
|
+
throw new RateConfirmationMismatchError(
|
|
6
|
+
`Transaction chainID ${tx.chainID} does not match approved fromChainId ${intent.fromChainId}`
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
if (tx.account !== void 0 && tx.account !== "" && intent.sender !== "" && tx.account.toLowerCase() !== intent.sender.toLowerCase()) {
|
|
10
|
+
throw new RateConfirmationMismatchError(
|
|
11
|
+
`Transaction account ${tx.account} does not match approved sender ${intent.sender}`
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
if (tx.sender !== void 0 && tx.sender !== "" && intent.sender !== "" && tx.sender.toLowerCase() !== intent.sender.toLowerCase()) {
|
|
15
|
+
throw new RateConfirmationMismatchError(
|
|
16
|
+
`Transaction sender ${tx.sender} does not match approved sender ${intent.sender}`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
assertRateConfirmationMatchesIntent
|
|
23
|
+
};
|
package/helpers/index.d.ts
CHANGED
|
@@ -3,7 +3,9 @@ export * from './decodeLoginToken';
|
|
|
3
3
|
export * from './decodeToken';
|
|
4
4
|
export * from './getApiURL';
|
|
5
5
|
export * from './getBridgeURL';
|
|
6
|
+
export * from './getDisplayName';
|
|
6
7
|
export * from './getMvxApiURL';
|
|
7
8
|
export * from './getMvxChainId';
|
|
8
9
|
export * from './getMvxExplorerAddress';
|
|
10
|
+
export * from './safeImageUrl';
|
|
9
11
|
export * from './serializeTransaction';
|
package/helpers/index.js
CHANGED
|
@@ -6,9 +6,11 @@ const helpers_decodeLoginToken = require("./decodeLoginToken.js");
|
|
|
6
6
|
const helpers_decodeToken = require("./decodeToken.js");
|
|
7
7
|
const helpers_getApiURL = require("./getApiURL.js");
|
|
8
8
|
const helpers_getBridgeURL = require("./getBridgeURL.js");
|
|
9
|
+
const helpers_getDisplayName = require("./getDisplayName.js");
|
|
9
10
|
const helpers_getMvxApiURL = require("./getMvxApiURL.js");
|
|
10
11
|
const helpers_getMvxChainId = require("./getMvxChainId.js");
|
|
11
12
|
const helpers_getMvxExplorerAddress = require("./getMvxExplorerAddress.js");
|
|
13
|
+
const helpers_safeImageUrl = require("./safeImageUrl.js");
|
|
12
14
|
const helpers_serializeTransaction = require("./serializeTransaction.js");
|
|
13
15
|
exports.decodeBase64 = helpers_base64Utils.decodeBase64;
|
|
14
16
|
exports.encodeToBase64 = helpers_base64Utils.encodeToBase64;
|
|
@@ -17,7 +19,9 @@ exports.decodeLoginToken = helpers_decodeLoginToken.decodeLoginToken;
|
|
|
17
19
|
exports.decodeToken = helpers_decodeToken.decodeToken;
|
|
18
20
|
exports.getApiURL = helpers_getApiURL.getApiURL;
|
|
19
21
|
exports.getBridgeURL = helpers_getBridgeURL.getBridgeURL;
|
|
22
|
+
exports.getDisplayName = helpers_getDisplayName.getDisplayName;
|
|
20
23
|
exports.getMvxApiURL = helpers_getMvxApiURL.getMvxApiURL;
|
|
21
24
|
exports.getMvxChainId = helpers_getMvxChainId.getMvxChainId;
|
|
22
25
|
exports.getMvxExplorerAddress = helpers_getMvxExplorerAddress.getMvxExplorerAddress;
|
|
26
|
+
exports.safeImageUrl = helpers_safeImageUrl.safeImageUrl;
|
|
23
27
|
exports.serializeTransaction = helpers_serializeTransaction.serializeTransaction;
|
package/helpers/index.mjs
CHANGED
|
@@ -3,9 +3,11 @@ import { decodeLoginToken } from "./decodeLoginToken.mjs";
|
|
|
3
3
|
import { decodeToken } from "./decodeToken.mjs";
|
|
4
4
|
import { getApiURL } from "./getApiURL.mjs";
|
|
5
5
|
import { getBridgeURL } from "./getBridgeURL.mjs";
|
|
6
|
+
import { getDisplayName } from "./getDisplayName.mjs";
|
|
6
7
|
import { getMvxApiURL } from "./getMvxApiURL.mjs";
|
|
7
8
|
import { getMvxChainId } from "./getMvxChainId.mjs";
|
|
8
9
|
import { getMvxExplorerAddress } from "./getMvxExplorerAddress.mjs";
|
|
10
|
+
import { safeImageUrl } from "./safeImageUrl.mjs";
|
|
9
11
|
import { serializeTransaction } from "./serializeTransaction.mjs";
|
|
10
12
|
export {
|
|
11
13
|
decodeBase64,
|
|
@@ -14,9 +16,11 @@ export {
|
|
|
14
16
|
encodeToBase64,
|
|
15
17
|
getApiURL,
|
|
16
18
|
getBridgeURL,
|
|
19
|
+
getDisplayName,
|
|
17
20
|
getMvxApiURL,
|
|
18
21
|
getMvxChainId,
|
|
19
22
|
getMvxExplorerAddress,
|
|
20
23
|
isStringBase64,
|
|
24
|
+
safeImageUrl,
|
|
21
25
|
serializeTransaction
|
|
22
26
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function safeImageUrl(url: string | undefined, fallback?: string): string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const BLOCKED_PREFIXES = ["data:", "javascript:", "file:", "blob:"];
|
|
5
|
+
const MAX_URL_LENGTH = 2048;
|
|
6
|
+
function safeImageUrl(url, fallback = "") {
|
|
7
|
+
if (!url || typeof url !== "string" || url.length === 0) {
|
|
8
|
+
return fallback;
|
|
9
|
+
}
|
|
10
|
+
if (url.length > MAX_URL_LENGTH) {
|
|
11
|
+
return fallback;
|
|
12
|
+
}
|
|
13
|
+
const lower = url.toLowerCase();
|
|
14
|
+
for (const prefix of BLOCKED_PREFIXES) {
|
|
15
|
+
if (lower.startsWith(prefix)) {
|
|
16
|
+
return fallback;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (!lower.startsWith("https://")) {
|
|
20
|
+
return fallback;
|
|
21
|
+
}
|
|
22
|
+
return url;
|
|
23
|
+
}
|
|
24
|
+
exports.safeImageUrl = safeImageUrl;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const BLOCKED_PREFIXES = ["data:", "javascript:", "file:", "blob:"];
|
|
2
|
+
const MAX_URL_LENGTH = 2048;
|
|
3
|
+
function safeImageUrl(url, fallback = "") {
|
|
4
|
+
if (!url || typeof url !== "string" || url.length === 0) {
|
|
5
|
+
return fallback;
|
|
6
|
+
}
|
|
7
|
+
if (url.length > MAX_URL_LENGTH) {
|
|
8
|
+
return fallback;
|
|
9
|
+
}
|
|
10
|
+
const lower = url.toLowerCase();
|
|
11
|
+
for (const prefix of BLOCKED_PREFIXES) {
|
|
12
|
+
if (lower.startsWith(prefix)) {
|
|
13
|
+
return fallback;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
if (!lower.startsWith("https://")) {
|
|
17
|
+
return fallback;
|
|
18
|
+
}
|
|
19
|
+
return url;
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
safeImageUrl
|
|
23
|
+
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
4
|
function serializeTransaction(transaction) {
|
|
5
5
|
return JSON.stringify(transaction, (_key, value) => {
|
|
6
|
-
return typeof value === "bigint" ?
|
|
6
|
+
return typeof value === "bigint" ? value.toString() : value;
|
|
7
7
|
});
|
|
8
8
|
}
|
|
9
9
|
exports.serializeTransaction = serializeTransaction;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
const types_errors = require("../../types/errors.js");
|
|
4
|
+
const helpers_assertRateConfirmationMatchesIntent = require("../assertRateConfirmationMatchesIntent.js");
|
|
5
|
+
const makeTransaction = (overrides = {}) => ({
|
|
6
|
+
to: "0xdeadbeef",
|
|
7
|
+
data: "0x",
|
|
8
|
+
gasLimit: BigInt(21e3),
|
|
9
|
+
value: BigInt(0),
|
|
10
|
+
account: "0xSender",
|
|
11
|
+
txHash: "",
|
|
12
|
+
...overrides
|
|
13
|
+
});
|
|
14
|
+
describe("assertRateConfirmationMatchesIntent", () => {
|
|
15
|
+
const intent = { fromChainId: "1", sender: "0xSender" };
|
|
16
|
+
it("does not throw for an empty transactions array", () => {
|
|
17
|
+
expect(() => helpers_assertRateConfirmationMatchesIntent.assertRateConfirmationMatchesIntent(intent, [])).not.toThrow();
|
|
18
|
+
});
|
|
19
|
+
it("does not throw when chainID and account match", () => {
|
|
20
|
+
const tx = makeTransaction({ chainID: "1", account: "0xSender" });
|
|
21
|
+
expect(
|
|
22
|
+
() => helpers_assertRateConfirmationMatchesIntent.assertRateConfirmationMatchesIntent(intent, [tx])
|
|
23
|
+
).not.toThrow();
|
|
24
|
+
});
|
|
25
|
+
it("does not throw when chainID is undefined (field absent)", () => {
|
|
26
|
+
const tx = makeTransaction({ account: "0xSender" });
|
|
27
|
+
expect(
|
|
28
|
+
() => helpers_assertRateConfirmationMatchesIntent.assertRateConfirmationMatchesIntent(intent, [tx])
|
|
29
|
+
).not.toThrow();
|
|
30
|
+
});
|
|
31
|
+
it("throws RateConfirmationMismatchError when chainID does not match fromChainId", () => {
|
|
32
|
+
const tx = makeTransaction({ chainID: "999", account: "0xSender" });
|
|
33
|
+
expect(() => helpers_assertRateConfirmationMatchesIntent.assertRateConfirmationMatchesIntent(intent, [tx])).toThrow(
|
|
34
|
+
types_errors.RateConfirmationMismatchError
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
it("throws RateConfirmationMismatchError when account does not match sender (case-insensitive)", () => {
|
|
38
|
+
const tx = makeTransaction({ account: "0xAttacker" });
|
|
39
|
+
expect(() => helpers_assertRateConfirmationMatchesIntent.assertRateConfirmationMatchesIntent(intent, [tx])).toThrow(
|
|
40
|
+
types_errors.RateConfirmationMismatchError
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
it("does not throw when account matches sender case-insensitively", () => {
|
|
44
|
+
const tx = makeTransaction({ account: "0xsender" });
|
|
45
|
+
const intentLower = { fromChainId: "1", sender: "0xSENDER" };
|
|
46
|
+
expect(
|
|
47
|
+
() => helpers_assertRateConfirmationMatchesIntent.assertRateConfirmationMatchesIntent(intentLower, [tx])
|
|
48
|
+
).not.toThrow();
|
|
49
|
+
});
|
|
50
|
+
it("throws RateConfirmationMismatchError when MvX sender field does not match", () => {
|
|
51
|
+
const tx = makeTransaction({ account: "0xSender", sender: "erd1attacker" });
|
|
52
|
+
const mvxIntent = { fromChainId: "1", sender: "erd1legit" };
|
|
53
|
+
expect(() => helpers_assertRateConfirmationMatchesIntent.assertRateConfirmationMatchesIntent(mvxIntent, [tx])).toThrow(
|
|
54
|
+
types_errors.RateConfirmationMismatchError
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
it("throws on the bad transaction when mixed valid and invalid transactions are present", () => {
|
|
58
|
+
const goodTx = makeTransaction({ chainID: "1", account: "0xSender" });
|
|
59
|
+
const badTx = makeTransaction({ chainID: "999", account: "0xSender" });
|
|
60
|
+
expect(
|
|
61
|
+
() => helpers_assertRateConfirmationMatchesIntent.assertRateConfirmationMatchesIntent(intent, [goodTx, badTx])
|
|
62
|
+
).toThrow(types_errors.RateConfirmationMismatchError);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { RateConfirmationMismatchError } from "../../types/errors.mjs";
|
|
2
|
+
import { assertRateConfirmationMatchesIntent } from "../assertRateConfirmationMatchesIntent.mjs";
|
|
3
|
+
const makeTransaction = (overrides = {}) => ({
|
|
4
|
+
to: "0xdeadbeef",
|
|
5
|
+
data: "0x",
|
|
6
|
+
gasLimit: BigInt(21e3),
|
|
7
|
+
value: BigInt(0),
|
|
8
|
+
account: "0xSender",
|
|
9
|
+
txHash: "",
|
|
10
|
+
...overrides
|
|
11
|
+
});
|
|
12
|
+
describe("assertRateConfirmationMatchesIntent", () => {
|
|
13
|
+
const intent = { fromChainId: "1", sender: "0xSender" };
|
|
14
|
+
it("does not throw for an empty transactions array", () => {
|
|
15
|
+
expect(() => assertRateConfirmationMatchesIntent(intent, [])).not.toThrow();
|
|
16
|
+
});
|
|
17
|
+
it("does not throw when chainID and account match", () => {
|
|
18
|
+
const tx = makeTransaction({ chainID: "1", account: "0xSender" });
|
|
19
|
+
expect(
|
|
20
|
+
() => assertRateConfirmationMatchesIntent(intent, [tx])
|
|
21
|
+
).not.toThrow();
|
|
22
|
+
});
|
|
23
|
+
it("does not throw when chainID is undefined (field absent)", () => {
|
|
24
|
+
const tx = makeTransaction({ account: "0xSender" });
|
|
25
|
+
expect(
|
|
26
|
+
() => assertRateConfirmationMatchesIntent(intent, [tx])
|
|
27
|
+
).not.toThrow();
|
|
28
|
+
});
|
|
29
|
+
it("throws RateConfirmationMismatchError when chainID does not match fromChainId", () => {
|
|
30
|
+
const tx = makeTransaction({ chainID: "999", account: "0xSender" });
|
|
31
|
+
expect(() => assertRateConfirmationMatchesIntent(intent, [tx])).toThrow(
|
|
32
|
+
RateConfirmationMismatchError
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
it("throws RateConfirmationMismatchError when account does not match sender (case-insensitive)", () => {
|
|
36
|
+
const tx = makeTransaction({ account: "0xAttacker" });
|
|
37
|
+
expect(() => assertRateConfirmationMatchesIntent(intent, [tx])).toThrow(
|
|
38
|
+
RateConfirmationMismatchError
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
it("does not throw when account matches sender case-insensitively", () => {
|
|
42
|
+
const tx = makeTransaction({ account: "0xsender" });
|
|
43
|
+
const intentLower = { fromChainId: "1", sender: "0xSENDER" };
|
|
44
|
+
expect(
|
|
45
|
+
() => assertRateConfirmationMatchesIntent(intentLower, [tx])
|
|
46
|
+
).not.toThrow();
|
|
47
|
+
});
|
|
48
|
+
it("throws RateConfirmationMismatchError when MvX sender field does not match", () => {
|
|
49
|
+
const tx = makeTransaction({ account: "0xSender", sender: "erd1attacker" });
|
|
50
|
+
const mvxIntent = { fromChainId: "1", sender: "erd1legit" };
|
|
51
|
+
expect(() => assertRateConfirmationMatchesIntent(mvxIntent, [tx])).toThrow(
|
|
52
|
+
RateConfirmationMismatchError
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
it("throws on the bad transaction when mixed valid and invalid transactions are present", () => {
|
|
56
|
+
const goodTx = makeTransaction({ chainID: "1", account: "0xSender" });
|
|
57
|
+
const badTx = makeTransaction({ chainID: "999", account: "0xSender" });
|
|
58
|
+
expect(
|
|
59
|
+
() => assertRateConfirmationMatchesIntent(intent, [goodTx, badTx])
|
|
60
|
+
).toThrow(RateConfirmationMismatchError);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
const helpers_safeImageUrl = require("../safeImageUrl.js");
|
|
4
|
+
describe("safeImageUrl", () => {
|
|
5
|
+
it("passes through a valid https:// URL unchanged", () => {
|
|
6
|
+
const url = "https://example.com/icon.png";
|
|
7
|
+
expect(helpers_safeImageUrl.safeImageUrl(url)).toBe(url);
|
|
8
|
+
});
|
|
9
|
+
it("rejects an http:// URL and returns the default fallback", () => {
|
|
10
|
+
expect(helpers_safeImageUrl.safeImageUrl("http://example.com/icon.png")).toBe("");
|
|
11
|
+
});
|
|
12
|
+
it("rejects a data: URL", () => {
|
|
13
|
+
expect(helpers_safeImageUrl.safeImageUrl("data:image/png;base64,abc123")).toBe("");
|
|
14
|
+
});
|
|
15
|
+
it("rejects a javascript: URL", () => {
|
|
16
|
+
expect(helpers_safeImageUrl.safeImageUrl("javascript:alert(1)")).toBe("");
|
|
17
|
+
});
|
|
18
|
+
it("rejects a file: URL", () => {
|
|
19
|
+
expect(helpers_safeImageUrl.safeImageUrl("file:///etc/passwd")).toBe("");
|
|
20
|
+
});
|
|
21
|
+
it("rejects a blob: URL", () => {
|
|
22
|
+
expect(helpers_safeImageUrl.safeImageUrl("blob:https://example.com/some-uuid")).toBe("");
|
|
23
|
+
});
|
|
24
|
+
it("rejects an empty string", () => {
|
|
25
|
+
expect(helpers_safeImageUrl.safeImageUrl("")).toBe("");
|
|
26
|
+
});
|
|
27
|
+
it("rejects undefined", () => {
|
|
28
|
+
expect(helpers_safeImageUrl.safeImageUrl(void 0)).toBe("");
|
|
29
|
+
});
|
|
30
|
+
it("rejects a URL longer than 2048 characters", () => {
|
|
31
|
+
const url = "https://example.com/" + "a".repeat(2030);
|
|
32
|
+
expect(url.length).toBeGreaterThan(2048);
|
|
33
|
+
expect(helpers_safeImageUrl.safeImageUrl(url)).toBe("");
|
|
34
|
+
});
|
|
35
|
+
it("allows a URL of exactly 2048 characters", () => {
|
|
36
|
+
const prefix = "https://example.com/";
|
|
37
|
+
const url = prefix + "a".repeat(2048 - prefix.length);
|
|
38
|
+
expect(url.length).toBe(2048);
|
|
39
|
+
expect(helpers_safeImageUrl.safeImageUrl(url)).toBe(url);
|
|
40
|
+
});
|
|
41
|
+
it("returns the custom fallback when URL is invalid", () => {
|
|
42
|
+
const fallback = "https://cdn.example.com/default.svg";
|
|
43
|
+
expect(helpers_safeImageUrl.safeImageUrl("http://bad.example.com/icon.png", fallback)).toBe(
|
|
44
|
+
fallback
|
|
45
|
+
);
|
|
46
|
+
expect(helpers_safeImageUrl.safeImageUrl(void 0, fallback)).toBe(fallback);
|
|
47
|
+
expect(helpers_safeImageUrl.safeImageUrl("javascript:void(0)", fallback)).toBe(fallback);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { safeImageUrl } from "../safeImageUrl.mjs";
|
|
2
|
+
describe("safeImageUrl", () => {
|
|
3
|
+
it("passes through a valid https:// URL unchanged", () => {
|
|
4
|
+
const url = "https://example.com/icon.png";
|
|
5
|
+
expect(safeImageUrl(url)).toBe(url);
|
|
6
|
+
});
|
|
7
|
+
it("rejects an http:// URL and returns the default fallback", () => {
|
|
8
|
+
expect(safeImageUrl("http://example.com/icon.png")).toBe("");
|
|
9
|
+
});
|
|
10
|
+
it("rejects a data: URL", () => {
|
|
11
|
+
expect(safeImageUrl("data:image/png;base64,abc123")).toBe("");
|
|
12
|
+
});
|
|
13
|
+
it("rejects a javascript: URL", () => {
|
|
14
|
+
expect(safeImageUrl("javascript:alert(1)")).toBe("");
|
|
15
|
+
});
|
|
16
|
+
it("rejects a file: URL", () => {
|
|
17
|
+
expect(safeImageUrl("file:///etc/passwd")).toBe("");
|
|
18
|
+
});
|
|
19
|
+
it("rejects a blob: URL", () => {
|
|
20
|
+
expect(safeImageUrl("blob:https://example.com/some-uuid")).toBe("");
|
|
21
|
+
});
|
|
22
|
+
it("rejects an empty string", () => {
|
|
23
|
+
expect(safeImageUrl("")).toBe("");
|
|
24
|
+
});
|
|
25
|
+
it("rejects undefined", () => {
|
|
26
|
+
expect(safeImageUrl(void 0)).toBe("");
|
|
27
|
+
});
|
|
28
|
+
it("rejects a URL longer than 2048 characters", () => {
|
|
29
|
+
const url = "https://example.com/" + "a".repeat(2030);
|
|
30
|
+
expect(url.length).toBeGreaterThan(2048);
|
|
31
|
+
expect(safeImageUrl(url)).toBe("");
|
|
32
|
+
});
|
|
33
|
+
it("allows a URL of exactly 2048 characters", () => {
|
|
34
|
+
const prefix = "https://example.com/";
|
|
35
|
+
const url = prefix + "a".repeat(2048 - prefix.length);
|
|
36
|
+
expect(url.length).toBe(2048);
|
|
37
|
+
expect(safeImageUrl(url)).toBe(url);
|
|
38
|
+
});
|
|
39
|
+
it("returns the custom fallback when URL is invalid", () => {
|
|
40
|
+
const fallback = "https://cdn.example.com/default.svg";
|
|
41
|
+
expect(safeImageUrl("http://bad.example.com/icon.png", fallback)).toBe(
|
|
42
|
+
fallback
|
|
43
|
+
);
|
|
44
|
+
expect(safeImageUrl(void 0, fallback)).toBe(fallback);
|
|
45
|
+
expect(safeImageUrl("javascript:void(0)", fallback)).toBe(fallback);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
const helpers_serializeTransaction = require("../serializeTransaction.js");
|
|
4
|
+
const baseTransaction = {
|
|
5
|
+
to: "0x1234567890abcdef1234567890abcdef12345678",
|
|
6
|
+
data: "0x",
|
|
7
|
+
gasLimit: 21000n,
|
|
8
|
+
value: 0n,
|
|
9
|
+
account: "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
|
|
10
|
+
txHash: ""
|
|
11
|
+
};
|
|
12
|
+
describe("serializeTransaction", () => {
|
|
13
|
+
it("serialises a normal small BigInt correctly", () => {
|
|
14
|
+
const tx = { ...baseTransaction, value: 100n };
|
|
15
|
+
const result = JSON.parse(helpers_serializeTransaction.serializeTransaction(tx));
|
|
16
|
+
expect(result.value).toBe("100");
|
|
17
|
+
});
|
|
18
|
+
it("serialises a BigInt at exactly Number.MAX_SAFE_INTEGER correctly", () => {
|
|
19
|
+
const maxSafe = 9007199254740991n;
|
|
20
|
+
const tx = { ...baseTransaction, value: maxSafe };
|
|
21
|
+
const result = JSON.parse(helpers_serializeTransaction.serializeTransaction(tx));
|
|
22
|
+
expect(result.value).toBe("9007199254740991");
|
|
23
|
+
});
|
|
24
|
+
it("serialises 10 ETH in wei (above Number.MAX_SAFE_INTEGER) to the exact string without rounding", () => {
|
|
25
|
+
const tenEthInWei = 10000000000000000000n;
|
|
26
|
+
const tx = { ...baseTransaction, value: tenEthInWei };
|
|
27
|
+
const result = JSON.parse(helpers_serializeTransaction.serializeTransaction(tx));
|
|
28
|
+
expect(result.value).toBe("10000000000000000000");
|
|
29
|
+
});
|
|
30
|
+
it("serialises a value that would be corrupted by Number() to the exact string", () => {
|
|
31
|
+
const precisionLoss = 9007199254740993n;
|
|
32
|
+
const tx = { ...baseTransaction, value: precisionLoss };
|
|
33
|
+
const result = JSON.parse(helpers_serializeTransaction.serializeTransaction(tx));
|
|
34
|
+
expect(result.value).toBe("9007199254740993");
|
|
35
|
+
expect(result.value).not.toBe("9007199254740992");
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { serializeTransaction } from "../serializeTransaction.mjs";
|
|
2
|
+
const baseTransaction = {
|
|
3
|
+
to: "0x1234567890abcdef1234567890abcdef12345678",
|
|
4
|
+
data: "0x",
|
|
5
|
+
gasLimit: 21000n,
|
|
6
|
+
value: 0n,
|
|
7
|
+
account: "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
|
|
8
|
+
txHash: ""
|
|
9
|
+
};
|
|
10
|
+
describe("serializeTransaction", () => {
|
|
11
|
+
it("serialises a normal small BigInt correctly", () => {
|
|
12
|
+
const tx = { ...baseTransaction, value: 100n };
|
|
13
|
+
const result = JSON.parse(serializeTransaction(tx));
|
|
14
|
+
expect(result.value).toBe("100");
|
|
15
|
+
});
|
|
16
|
+
it("serialises a BigInt at exactly Number.MAX_SAFE_INTEGER correctly", () => {
|
|
17
|
+
const maxSafe = 9007199254740991n;
|
|
18
|
+
const tx = { ...baseTransaction, value: maxSafe };
|
|
19
|
+
const result = JSON.parse(serializeTransaction(tx));
|
|
20
|
+
expect(result.value).toBe("9007199254740991");
|
|
21
|
+
});
|
|
22
|
+
it("serialises 10 ETH in wei (above Number.MAX_SAFE_INTEGER) to the exact string without rounding", () => {
|
|
23
|
+
const tenEthInWei = 10000000000000000000n;
|
|
24
|
+
const tx = { ...baseTransaction, value: tenEthInWei };
|
|
25
|
+
const result = JSON.parse(serializeTransaction(tx));
|
|
26
|
+
expect(result.value).toBe("10000000000000000000");
|
|
27
|
+
});
|
|
28
|
+
it("serialises a value that would be corrupted by Number() to the exact string", () => {
|
|
29
|
+
const precisionLoss = 9007199254740993n;
|
|
30
|
+
const tx = { ...baseTransaction, value: precisionLoss };
|
|
31
|
+
const result = JSON.parse(serializeTransaction(tx));
|
|
32
|
+
expect(result.value).toBe("9007199254740993");
|
|
33
|
+
expect(result.value).not.toBe("9007199254740992");
|
|
34
|
+
});
|
|
35
|
+
});
|
package/index.js
CHANGED
|
@@ -15,9 +15,11 @@ const helpers_decodeLoginToken = require("./helpers/decodeLoginToken.js");
|
|
|
15
15
|
const helpers_decodeToken = require("./helpers/decodeToken.js");
|
|
16
16
|
const helpers_getApiURL = require("./helpers/getApiURL.js");
|
|
17
17
|
const helpers_getBridgeURL = require("./helpers/getBridgeURL.js");
|
|
18
|
+
const helpers_getDisplayName = require("./helpers/getDisplayName.js");
|
|
18
19
|
const helpers_getMvxApiURL = require("./helpers/getMvxApiURL.js");
|
|
19
20
|
const helpers_getMvxChainId = require("./helpers/getMvxChainId.js");
|
|
20
21
|
const helpers_getMvxExplorerAddress = require("./helpers/getMvxExplorerAddress.js");
|
|
22
|
+
const helpers_safeImageUrl = require("./helpers/safeImageUrl.js");
|
|
21
23
|
const helpers_serializeTransaction = require("./helpers/serializeTransaction.js");
|
|
22
24
|
;/* empty css */
|
|
23
25
|
const reactjs_components_AccountAddress_AccountAddress = require("./reactjs/components/AccountAddress/AccountAddress.js");
|
|
@@ -104,9 +106,11 @@ exports.decodeLoginToken = helpers_decodeLoginToken.decodeLoginToken;
|
|
|
104
106
|
exports.decodeToken = helpers_decodeToken.decodeToken;
|
|
105
107
|
exports.getApiURL = helpers_getApiURL.getApiURL;
|
|
106
108
|
exports.getBridgeURL = helpers_getBridgeURL.getBridgeURL;
|
|
109
|
+
exports.getDisplayName = helpers_getDisplayName.getDisplayName;
|
|
107
110
|
exports.getMvxApiURL = helpers_getMvxApiURL.getMvxApiURL;
|
|
108
111
|
exports.getMvxChainId = helpers_getMvxChainId.getMvxChainId;
|
|
109
112
|
exports.getMvxExplorerAddress = helpers_getMvxExplorerAddress.getMvxExplorerAddress;
|
|
113
|
+
exports.safeImageUrl = helpers_safeImageUrl.safeImageUrl;
|
|
110
114
|
exports.serializeTransaction = helpers_serializeTransaction.serializeTransaction;
|
|
111
115
|
exports.AccountAddress = reactjs_components_AccountAddress_AccountAddress.AccountAddress;
|
|
112
116
|
exports.AmountCard = reactjs_components_AmountCard_AmountCard.AmountCard;
|
|
@@ -161,12 +165,12 @@ exports.SuiMethods = reactjs_init_init.SuiMethods;
|
|
|
161
165
|
exports.init = reactjs_init_init.init;
|
|
162
166
|
exports.useGetAllTokensQuery = reactjs_queries_useGetAllTokens_query.useGetAllTokensQuery;
|
|
163
167
|
exports.useGetChainsQuery = reactjs_queries_useGetChains_query.useGetChainsQuery;
|
|
164
|
-
exports.invalidateEvmTokensBalances = reactjs_queries_useGetNonMvxTokensBalances_query.invalidateEvmTokensBalances;
|
|
165
168
|
exports.useGetNonMvxTokensBalancesQuery = reactjs_queries_useGetNonMvxTokensBalances_query.useGetNonMvxTokensBalancesQuery;
|
|
166
|
-
exports.
|
|
169
|
+
exports.useInvalidateEvmTokensBalances = reactjs_queries_useGetNonMvxTokensBalances_query.useInvalidateEvmTokensBalances;
|
|
167
170
|
exports.useGetHistoryQuery = reactjs_queries_useGetHistory_query.useGetHistoryQuery;
|
|
168
|
-
exports.
|
|
171
|
+
exports.useInvalidateHistoryQuery = reactjs_queries_useGetHistory_query.useInvalidateHistoryQuery;
|
|
169
172
|
exports.useGetMvxTokensBalancesQuery = reactjs_queries_useGetMvxTokensBalances_query.useGetMvxTokensBalancesQuery;
|
|
173
|
+
exports.useInvalidateMvxTokensBalancesQuery = reactjs_queries_useGetMvxTokensBalances_query.useInvalidateMvxTokensBalancesQuery;
|
|
170
174
|
exports.useGetRateMutation = reactjs_queries_useGetRate_mutation.useGetRateMutation;
|
|
171
175
|
exports.delay = reactjs_utils_delay.delay;
|
|
172
176
|
exports.formatAmount = reactjs_utils_formatAmount.formatAmount;
|
package/index.mjs
CHANGED
|
@@ -12,9 +12,11 @@ import { decodeLoginToken } from "./helpers/decodeLoginToken.mjs";
|
|
|
12
12
|
import { decodeToken } from "./helpers/decodeToken.mjs";
|
|
13
13
|
import { getApiURL } from "./helpers/getApiURL.mjs";
|
|
14
14
|
import { getBridgeURL } from "./helpers/getBridgeURL.mjs";
|
|
15
|
+
import { getDisplayName } from "./helpers/getDisplayName.mjs";
|
|
15
16
|
import { getMvxApiURL } from "./helpers/getMvxApiURL.mjs";
|
|
16
17
|
import { getMvxChainId } from "./helpers/getMvxChainId.mjs";
|
|
17
18
|
import { getMvxExplorerAddress } from "./helpers/getMvxExplorerAddress.mjs";
|
|
19
|
+
import { safeImageUrl } from "./helpers/safeImageUrl.mjs";
|
|
18
20
|
import { serializeTransaction } from "./helpers/serializeTransaction.mjs";
|
|
19
21
|
/* empty css */
|
|
20
22
|
import { AccountAddress } from "./reactjs/components/AccountAddress/AccountAddress.mjs";
|
|
@@ -66,9 +68,9 @@ import { useSuiConnect } from "./reactjs/hooks/useSuiConnect.mjs";
|
|
|
66
68
|
import { SuiMethods, init } from "./reactjs/init/init.mjs";
|
|
67
69
|
import { useGetAllTokensQuery } from "./reactjs/queries/useGetAllTokens.query.mjs";
|
|
68
70
|
import { useGetChainsQuery } from "./reactjs/queries/useGetChains.query.mjs";
|
|
69
|
-
import {
|
|
70
|
-
import {
|
|
71
|
-
import {
|
|
71
|
+
import { useGetNonMvxTokensBalancesQuery, useInvalidateEvmTokensBalances } from "./reactjs/queries/useGetNonMvxTokensBalances.query.mjs";
|
|
72
|
+
import { useGetHistoryQuery, useInvalidateHistoryQuery } from "./reactjs/queries/useGetHistory.query.mjs";
|
|
73
|
+
import { useGetMvxTokensBalancesQuery, useInvalidateMvxTokensBalancesQuery } from "./reactjs/queries/useGetMvxTokensBalances.query.mjs";
|
|
72
74
|
import { useGetRateMutation } from "./reactjs/queries/useGetRate.mutation.mjs";
|
|
73
75
|
import { delay } from "./reactjs/utils/delay.mjs";
|
|
74
76
|
import { formatAmount } from "./reactjs/utils/formatAmount.mjs";
|
|
@@ -133,6 +135,7 @@ export {
|
|
|
133
135
|
getChains,
|
|
134
136
|
getCleanStringAmount,
|
|
135
137
|
getCompletePathname,
|
|
138
|
+
getDisplayName,
|
|
136
139
|
getInitialTokens,
|
|
137
140
|
getMvxApiURL,
|
|
138
141
|
getMvxChainId,
|
|
@@ -144,9 +147,6 @@ export {
|
|
|
144
147
|
getTransactions,
|
|
145
148
|
hasEnoughFunds,
|
|
146
149
|
init,
|
|
147
|
-
invalidateEvmTokensBalances,
|
|
148
|
-
invalidateHistoryQuery,
|
|
149
|
-
invalidateMvxTokensBalancesQuery,
|
|
150
150
|
isStringBase64,
|
|
151
151
|
isStringFloat,
|
|
152
152
|
mxClsx,
|
|
@@ -154,6 +154,7 @@ export {
|
|
|
154
154
|
removeCommas,
|
|
155
155
|
roundAmount,
|
|
156
156
|
safeDocument,
|
|
157
|
+
safeImageUrl,
|
|
157
158
|
safeWindow,
|
|
158
159
|
sendTransactions,
|
|
159
160
|
serializeTransaction,
|
|
@@ -182,6 +183,9 @@ export {
|
|
|
182
183
|
useGetMvxTokensBalancesQuery,
|
|
183
184
|
useGetNonMvxTokensBalancesQuery,
|
|
184
185
|
useGetRateMutation,
|
|
186
|
+
useInvalidateEvmTokensBalances,
|
|
187
|
+
useInvalidateHistoryQuery,
|
|
188
|
+
useInvalidateMvxTokensBalancesQuery,
|
|
185
189
|
useResolveTokenChain,
|
|
186
190
|
useSecondAmountSchema,
|
|
187
191
|
useSendTransactions,
|