@rozoai/intent-common 0.0.32-beta.1 → 0.0.32-beta.3
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/README.md +134 -0
- package/dist/api/base.d.ts +1 -1
- package/dist/api/base.js +2 -1
- package/dist/api/base.js.map +1 -1
- package/dist/api/fee.d.ts +2 -1
- package/dist/api/fee.js +5 -1
- package/dist/api/fee.js.map +1 -1
- package/dist/api/new-payment.d.ts +319 -0
- package/dist/api/new-payment.js +140 -0
- package/dist/api/new-payment.js.map +1 -0
- package/dist/api/payment.d.ts +106 -5
- package/dist/api/payment.js +117 -10
- package/dist/api/payment.js.map +1 -1
- package/dist/bridge.d.ts +84 -46
- package/dist/bridge.js +183 -169
- package/dist/bridge.js.map +1 -1
- package/dist/chain.d.ts +6 -0
- package/dist/chain.js +38 -14
- package/dist/chain.js.map +1 -1
- package/dist/daimoPay.d.ts +9 -9
- package/dist/daimoPay.js +5 -0
- package/dist/daimoPay.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/token.d.ts +9 -0
- package/dist/token.js +111 -17
- package/dist/token.js.map +1 -1
- package/dist/validation.d.ts +9 -0
- package/dist/validation.js +47 -0
- package/dist/validation.js.map +1 -0
- package/package.json +4 -2
- package/src/api/base.ts +3 -1
- package/src/api/fee.ts +8 -2
- package/src/api/new-payment.ts +433 -0
- package/src/api/payment.ts +172 -13
- package/src/bridge.ts +225 -201
- package/src/chain.ts +40 -13
- package/src/daimoPay.ts +17 -9
- package/src/index.ts +2 -0
- package/src/token.ts +124 -18
- package/src/validation.ts +54 -0
- package/test/bridge.test.ts +393 -0
- package/dist/chainAddress.d.ts +0 -27
- package/dist/chainAddress.js +0 -87
- package/dist/chainAddress.js.map +0 -1
- package/dist/supportedChain.d.ts +0 -27
- package/dist/supportedChain.js +0 -87
- package/dist/supportedChain.js.map +0 -1
- package/dist/supportedChains.d.ts +0 -27
- package/dist/supportedChains.js +0 -87
- package/dist/supportedChains.js.map +0 -1
package/src/daimoPay.ts
CHANGED
|
@@ -190,16 +190,16 @@ export type RozoPayDehydratedOrder = {
|
|
|
190
190
|
export type RozoPayHydratedOrder = {
|
|
191
191
|
mode: RozoPayOrderMode.HYDRATED;
|
|
192
192
|
id: bigint;
|
|
193
|
-
intentAddr:
|
|
193
|
+
intentAddr: string;
|
|
194
194
|
/** Nullable because old intents don't record escrow address. */
|
|
195
|
-
escrowContractAddress: Address | null;
|
|
195
|
+
// escrowContractAddress: Address | null;
|
|
196
196
|
/** Nullable because old intents don't record bridger address. */
|
|
197
|
-
bridgerContractAddress: Address | null;
|
|
197
|
+
// bridgerContractAddress: Address | null;
|
|
198
198
|
/** @deprecated included for backcompat with old versions. Remove soon. */
|
|
199
|
-
handoffAddr: Address;
|
|
200
|
-
bridgeTokenOutOptions: RozoPayTokenAmount[];
|
|
201
|
-
selectedBridgeTokenOutAddr: Address | null;
|
|
202
|
-
selectedBridgeTokenOutAmount: bigint | null;
|
|
199
|
+
// handoffAddr: Address;
|
|
200
|
+
// bridgeTokenOutOptions: RozoPayTokenAmount[];
|
|
201
|
+
// selectedBridgeTokenOutAddr: Address | null;
|
|
202
|
+
// selectedBridgeTokenOutAmount: bigint | null;
|
|
203
203
|
destFinalCallTokenAmount: RozoPayTokenAmount;
|
|
204
204
|
destFinalCall: OnChainCall;
|
|
205
205
|
usdValue: number;
|
|
@@ -208,7 +208,7 @@ export type RozoPayHydratedOrder = {
|
|
|
208
208
|
sourceFulfillerAddr: Address | SolanaPublicKey | StellarPublicKey | null;
|
|
209
209
|
sourceTokenAmount: RozoPayTokenAmount | null;
|
|
210
210
|
sourceInitiateTxHash: Hex | null;
|
|
211
|
-
sourceStartTxHash: Hex | null;
|
|
211
|
+
// sourceStartTxHash: Hex | null;
|
|
212
212
|
sourceStatus: RozoPayOrderStatusSource;
|
|
213
213
|
destStatus: RozoPayOrderStatusDest;
|
|
214
214
|
destFastFinishTxHash: Hex | null;
|
|
@@ -429,6 +429,12 @@ export enum DepositAddressPaymentOptions {
|
|
|
429
429
|
STELLAR = "Stellar",
|
|
430
430
|
WORLD = "Worldchain",
|
|
431
431
|
|
|
432
|
+
SOLANA_USDT = "USDT on Solana",
|
|
433
|
+
SOLANA_USDC = "USDC on Solana",
|
|
434
|
+
BASE_USDC = "USDC on Base",
|
|
435
|
+
ETHEREUM_USDT = "USDT on Ethereum",
|
|
436
|
+
ETHEREUM_USDC = "USDC on Ethereum",
|
|
437
|
+
|
|
432
438
|
/** @deprecated */
|
|
433
439
|
BITCOIN = "Bitcoin",
|
|
434
440
|
/** @deprecated */
|
|
@@ -449,6 +455,8 @@ export type DepositAddressPaymentOptionMetadata = {
|
|
|
449
455
|
id: DepositAddressPaymentOptions;
|
|
450
456
|
logoURI: string;
|
|
451
457
|
minimumUsd: number;
|
|
458
|
+
chainId: number;
|
|
459
|
+
token: Token;
|
|
452
460
|
};
|
|
453
461
|
|
|
454
462
|
export type DepositAddressPaymentOptionData = {
|
|
@@ -482,7 +490,7 @@ export interface RozoPayTokenAmount {
|
|
|
482
490
|
}
|
|
483
491
|
|
|
484
492
|
export type OnChainCall = {
|
|
485
|
-
to: Address;
|
|
493
|
+
to: Address | SolanaPublicKey | StellarPublicKey;
|
|
486
494
|
data: Hex;
|
|
487
495
|
value: bigint;
|
|
488
496
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "./api/fee";
|
|
2
|
+
export * from "./api/new-payment";
|
|
2
3
|
export * from "./api/payment";
|
|
3
4
|
export * from "./assert";
|
|
4
5
|
export * from "./bridge";
|
|
@@ -10,3 +11,4 @@ export * from "./primitiveTypes";
|
|
|
10
11
|
export * from "./retryBackoff";
|
|
11
12
|
export * from "./token";
|
|
12
13
|
export * from "./try";
|
|
14
|
+
export * from "./validation";
|
package/src/token.ts
CHANGED
|
@@ -2,10 +2,12 @@ import { Address, getAddress, zeroAddress } from "viem";
|
|
|
2
2
|
import { assertNotNull } from "./assert";
|
|
3
3
|
import {
|
|
4
4
|
arbitrum,
|
|
5
|
+
avalanche,
|
|
5
6
|
base,
|
|
6
7
|
bsc,
|
|
7
8
|
celo,
|
|
8
9
|
ethereum,
|
|
10
|
+
gnosis,
|
|
9
11
|
linea,
|
|
10
12
|
mantle,
|
|
11
13
|
optimism,
|
|
@@ -716,11 +718,22 @@ export const rozoSolanaUSDC: Token = token({
|
|
|
716
718
|
logoURI: TokenLogo.USDC,
|
|
717
719
|
});
|
|
718
720
|
|
|
721
|
+
export const rozoSolanaUSDT: Token = token({
|
|
722
|
+
chainId: rozoSolana.chainId,
|
|
723
|
+
token: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
|
|
724
|
+
decimals: 6,
|
|
725
|
+
fiatISO: "USD",
|
|
726
|
+
name: "Tether USD",
|
|
727
|
+
symbol: "USDT",
|
|
728
|
+
logoURI: TokenLogo.USDT,
|
|
729
|
+
});
|
|
730
|
+
|
|
719
731
|
const solanaTokens: Token[] = [
|
|
720
732
|
solanaUSDC,
|
|
721
733
|
solanaWSOL,
|
|
722
734
|
solanaSOL,
|
|
723
735
|
rozoSolanaUSDC,
|
|
736
|
+
rozoSolanaUSDT,
|
|
724
737
|
];
|
|
725
738
|
|
|
726
739
|
//
|
|
@@ -748,8 +761,8 @@ export const stellarUSDC: Token = token({
|
|
|
748
761
|
|
|
749
762
|
export const rozoStellarUSDC: Token = token({
|
|
750
763
|
chainId: rozoStellar.chainId,
|
|
751
|
-
token: "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
|
|
752
|
-
decimals:
|
|
764
|
+
token: "USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
|
|
765
|
+
decimals: 7,
|
|
753
766
|
fiatISO: "USD",
|
|
754
767
|
name: "USD Coin",
|
|
755
768
|
symbol: "USDC",
|
|
@@ -809,30 +822,109 @@ const worldchainTokens: Token[] = [
|
|
|
809
822
|
worldchainWLD,
|
|
810
823
|
];
|
|
811
824
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
+
//
|
|
826
|
+
// Gnosis
|
|
827
|
+
//
|
|
828
|
+
|
|
829
|
+
export const gnosisXDAI = nativeToken({
|
|
830
|
+
chainId: gnosis.chainId,
|
|
831
|
+
name: "xDAI",
|
|
832
|
+
symbol: "XDAI",
|
|
833
|
+
logoURI: TokenLogo.DAI,
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
export const gnosisUSDC: Token = token({
|
|
837
|
+
chainId: gnosis.chainId,
|
|
838
|
+
token: getAddress("0x2a22f9c3b484c3629090feed35f17ff8f88f76f0"),
|
|
839
|
+
decimals: 6,
|
|
840
|
+
fiatISO: "USD",
|
|
841
|
+
name: "USD Coin",
|
|
842
|
+
symbol: "USDC",
|
|
843
|
+
logoURI: TokenLogo.USDC,
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
export const gnosisUSDT: Token = token({
|
|
847
|
+
chainId: gnosis.chainId,
|
|
848
|
+
token: getAddress("0x4ecaba5870353805a9f068101a40e0f32ed605c6"),
|
|
849
|
+
decimals: 6,
|
|
850
|
+
fiatISO: "USD",
|
|
851
|
+
name: "Tether USD",
|
|
852
|
+
symbol: "USDT",
|
|
853
|
+
logoURI: TokenLogo.USDT,
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
const gnosisTokens: Token[] = [gnosisXDAI, gnosisUSDC, gnosisUSDT];
|
|
857
|
+
|
|
858
|
+
//
|
|
859
|
+
// Avalanche
|
|
860
|
+
//
|
|
861
|
+
|
|
862
|
+
export const avalancheAVAX = nativeToken({
|
|
863
|
+
chainId: avalanche.chainId,
|
|
864
|
+
name: "Avalanche",
|
|
865
|
+
symbol: "AVAX",
|
|
866
|
+
logoURI: TokenLogo.AVAX,
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
export const avalancheUSDC: Token = token({
|
|
870
|
+
chainId: avalanche.chainId,
|
|
871
|
+
token: getAddress("0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"),
|
|
872
|
+
decimals: 6,
|
|
873
|
+
fiatISO: "USD",
|
|
874
|
+
name: "USD Coin",
|
|
875
|
+
symbol: "USDC",
|
|
876
|
+
logoURI: TokenLogo.USDC,
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
export const avalancheUSDT: Token = token({
|
|
880
|
+
chainId: avalanche.chainId,
|
|
881
|
+
token: getAddress("0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7"),
|
|
882
|
+
decimals: 6,
|
|
883
|
+
fiatISO: "USD",
|
|
884
|
+
name: "Tether USD",
|
|
885
|
+
symbol: "USDT",
|
|
886
|
+
logoURI: TokenLogo.USDT,
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
const avalancheTokens: Token[] = [avalancheAVAX, avalancheUSDC, avalancheUSDT];
|
|
890
|
+
|
|
891
|
+
/** Support tokens for Rozo Pay */
|
|
892
|
+
export const supportedTokens: Map<number, Token[]> = new Map([
|
|
893
|
+
[arbitrum.chainId, [arbitrumUSDC, arbitrumUSDT]],
|
|
894
|
+
[avalanche.chainId, [avalancheUSDC, avalancheUSDT]],
|
|
895
|
+
[base.chainId, [baseUSDC]],
|
|
896
|
+
[ethereum.chainId, [ethereumUSDC, ethereumUSDT]],
|
|
897
|
+
[gnosis.chainId, [gnosisUSDC, gnosisUSDT]],
|
|
898
|
+
[optimism.chainId, [optimismUSDC, optimismUSDT]],
|
|
899
|
+
[polygon.chainId, [polygonUSDC, polygonUSDT]],
|
|
900
|
+
[rozoSolana.chainId, [rozoSolanaUSDC, rozoSolanaUSDT]],
|
|
901
|
+
[rozoStellar.chainId, [rozoStellarUSDC]],
|
|
825
902
|
]);
|
|
826
903
|
|
|
904
|
+
// const knownTokensByChain = new Map<number, Token[]>([
|
|
905
|
+
// [arbitrum.chainId, arbitrumTokens],
|
|
906
|
+
// [avalanche.chainId, avalancheTokens],
|
|
907
|
+
// [base.chainId, baseTokens],
|
|
908
|
+
// [bsc.chainId, bscTokens],
|
|
909
|
+
// [celo.chainId, celoTokens],
|
|
910
|
+
// [ethereum.chainId, ethereumTokens],
|
|
911
|
+
// [gnosis.chainId, gnosisTokens],
|
|
912
|
+
// [linea.chainId, lineaTokens],
|
|
913
|
+
// [mantle.chainId, mantleTokens],
|
|
914
|
+
// [optimism.chainId, optimismTokens],
|
|
915
|
+
// [polygon.chainId, polygonTokens],
|
|
916
|
+
// [rozoSolana.chainId, solanaTokens],
|
|
917
|
+
// [rozoStellar.chainId, stellarTokens],
|
|
918
|
+
// [worldchain.chainId, worldchainTokens],
|
|
919
|
+
// ]);
|
|
920
|
+
|
|
827
921
|
/**
|
|
828
922
|
* Common tokens, included for convenience.
|
|
829
923
|
*
|
|
830
924
|
* Rozo Pay supports payment in many more tokens. In general, the goal for
|
|
831
925
|
* Pay is to accept all tokens with DEX liquidity on any major chain.
|
|
832
926
|
*/
|
|
833
|
-
export const knownTokens: Token[] = Array.from(
|
|
834
|
-
knownTokensByChain.values()
|
|
835
|
-
).flat();
|
|
927
|
+
export const knownTokens: Token[] = Array.from(supportedTokens.values()).flat();
|
|
836
928
|
|
|
837
929
|
/* --------------------- Tokens By Address --------------------- */
|
|
838
930
|
|
|
@@ -982,6 +1074,20 @@ const tokensByChainAndType: Map<
|
|
|
982
1074
|
[TokenType.NATIVE_USDC]: rozoStellarUSDC,
|
|
983
1075
|
},
|
|
984
1076
|
],
|
|
1077
|
+
[
|
|
1078
|
+
gnosis.chainId,
|
|
1079
|
+
{
|
|
1080
|
+
[TokenType.NATIVE]: gnosisXDAI,
|
|
1081
|
+
[TokenType.NATIVE_USDC]: gnosisUSDC,
|
|
1082
|
+
},
|
|
1083
|
+
],
|
|
1084
|
+
[
|
|
1085
|
+
avalanche.chainId,
|
|
1086
|
+
{
|
|
1087
|
+
[TokenType.NATIVE]: avalancheAVAX,
|
|
1088
|
+
[TokenType.NATIVE_USDC]: avalancheUSDC,
|
|
1089
|
+
},
|
|
1090
|
+
],
|
|
985
1091
|
[
|
|
986
1092
|
worldchain.chainId,
|
|
987
1093
|
{
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import { Address } from "@stellar/stellar-sdk";
|
|
3
|
+
import { getAddress } from "viem";
|
|
4
|
+
import { Chain, supportedChains } from "./chain";
|
|
5
|
+
import { getKnownToken } from "./token";
|
|
6
|
+
|
|
7
|
+
// Type guards
|
|
8
|
+
export function isChainSupported(
|
|
9
|
+
chainId: number,
|
|
10
|
+
type?: "evm" | "solana" | "stellar"
|
|
11
|
+
): boolean {
|
|
12
|
+
return supportedChains.some(
|
|
13
|
+
(chain: Chain) =>
|
|
14
|
+
chain.chainId === chainId && (type ? chain.type === type : true)
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function isTokenSupported(
|
|
19
|
+
chainId: number,
|
|
20
|
+
tokenAddress: string
|
|
21
|
+
): boolean {
|
|
22
|
+
return !!getKnownToken(chainId, tokenAddress);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Validation helpers
|
|
26
|
+
export function isValidEvmAddress(address: string): boolean {
|
|
27
|
+
return !!getAddress(address);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function isValidSolanaAddress(address: string): boolean {
|
|
31
|
+
const key = new PublicKey(address);
|
|
32
|
+
return PublicKey.isOnCurve(key.toBytes());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function isValidStellarAddress(address: string): boolean {
|
|
36
|
+
return !!Address.fromString(address);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Validates that an address matches the expected format for a given chain
|
|
41
|
+
*/
|
|
42
|
+
export function validateAddressForChain(
|
|
43
|
+
chainId: number,
|
|
44
|
+
address: string
|
|
45
|
+
): boolean {
|
|
46
|
+
if (isChainSupported(chainId, "evm")) {
|
|
47
|
+
return !!getAddress(address);
|
|
48
|
+
} else if (isChainSupported(chainId, "solana")) {
|
|
49
|
+
return isValidSolanaAddress(address);
|
|
50
|
+
} else if (isChainSupported(chainId, "stellar")) {
|
|
51
|
+
return isValidStellarAddress(address);
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import test from "tape";
|
|
2
|
+
import { createPaymentBridgeConfig, PaymentBridgeConfig } from "../src/bridge";
|
|
3
|
+
import { base, polygon, rozoSolana, rozoStellar } from "../src/chain";
|
|
4
|
+
import {
|
|
5
|
+
baseUSDC,
|
|
6
|
+
polygonUSDC,
|
|
7
|
+
rozoSolanaUSDC,
|
|
8
|
+
rozoStellarUSDC,
|
|
9
|
+
} from "../src/token";
|
|
10
|
+
|
|
11
|
+
// Valid addresses for testing
|
|
12
|
+
const VALID_EVM_ADDRESS = "0x1a5FdBc891c5D4E6aD68064Ae45D43146D4F9f3a";
|
|
13
|
+
const VALID_SOLANA_ADDRESS = "E35325pbtxCRsA4uVoC3cyBDZy8BMpmxvsvGcHNUa18k";
|
|
14
|
+
const VALID_STELLAR_ADDRESS =
|
|
15
|
+
"GDATMUNQEPN4TPETV47LAKGJELK4DUHHDRPMGD3K5LOHUPXX2DI623KY";
|
|
16
|
+
|
|
17
|
+
test("createPaymentBridgeConfig - Cross-chain payment (Polygon USDC to Base USDC)", (t) => {
|
|
18
|
+
const config: PaymentBridgeConfig = {
|
|
19
|
+
toChain: base.chainId,
|
|
20
|
+
toToken: baseUSDC.token,
|
|
21
|
+
toAddress: VALID_EVM_ADDRESS,
|
|
22
|
+
toUnits: "1", // 1 USDC
|
|
23
|
+
preferredChain: polygon.chainId,
|
|
24
|
+
preferredTokenAddress: polygonUSDC.token,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const result = createPaymentBridgeConfig(config);
|
|
28
|
+
|
|
29
|
+
t.equal(
|
|
30
|
+
result.preferred.preferredChain,
|
|
31
|
+
String(polygon.chainId),
|
|
32
|
+
"Preferred chain should be Polygon"
|
|
33
|
+
);
|
|
34
|
+
t.equal(
|
|
35
|
+
result.preferred.preferredToken,
|
|
36
|
+
"USDC",
|
|
37
|
+
"Preferred token should be USDC"
|
|
38
|
+
);
|
|
39
|
+
t.equal(
|
|
40
|
+
result.preferred.preferredTokenAddress,
|
|
41
|
+
polygonUSDC.token,
|
|
42
|
+
"Preferred token address should match Polygon USDC"
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
t.equal(
|
|
46
|
+
result.destination.chainId,
|
|
47
|
+
String(base.chainId),
|
|
48
|
+
"Destination chain should be Base"
|
|
49
|
+
);
|
|
50
|
+
t.equal(
|
|
51
|
+
result.destination.tokenSymbol,
|
|
52
|
+
"USDC",
|
|
53
|
+
"Destination token symbol should be USDC"
|
|
54
|
+
);
|
|
55
|
+
t.equal(
|
|
56
|
+
result.destination.tokenAddress,
|
|
57
|
+
baseUSDC.token,
|
|
58
|
+
"Destination token address should match Base USDC"
|
|
59
|
+
);
|
|
60
|
+
t.equal(
|
|
61
|
+
result.destination.destinationAddress,
|
|
62
|
+
VALID_EVM_ADDRESS,
|
|
63
|
+
"Destination address should match"
|
|
64
|
+
);
|
|
65
|
+
t.equal(result.destination.amountUnits, "1", "Amount units should match");
|
|
66
|
+
|
|
67
|
+
t.equal(
|
|
68
|
+
result.isIntentPayment,
|
|
69
|
+
true,
|
|
70
|
+
"Should be an intent payment (different chains)"
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
t.end();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("createPaymentBridgeConfig - Same-chain payment (Base USDC to Base USDC)", (t) => {
|
|
77
|
+
const config: PaymentBridgeConfig = {
|
|
78
|
+
toChain: base.chainId,
|
|
79
|
+
toToken: baseUSDC.token,
|
|
80
|
+
toAddress: VALID_EVM_ADDRESS,
|
|
81
|
+
toUnits: "1",
|
|
82
|
+
preferredChain: base.chainId,
|
|
83
|
+
preferredTokenAddress: baseUSDC.token,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const result = createPaymentBridgeConfig(config);
|
|
87
|
+
|
|
88
|
+
t.equal(
|
|
89
|
+
result.preferred.preferredChain,
|
|
90
|
+
String(base.chainId),
|
|
91
|
+
"Preferred chain should be Base"
|
|
92
|
+
);
|
|
93
|
+
t.equal(
|
|
94
|
+
result.preferred.preferredToken,
|
|
95
|
+
"USDC",
|
|
96
|
+
"Preferred token should be USDC"
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
t.equal(
|
|
100
|
+
result.destination.chainId,
|
|
101
|
+
String(base.chainId),
|
|
102
|
+
"Destination chain should be Base"
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
t.equal(
|
|
106
|
+
result.isIntentPayment,
|
|
107
|
+
false,
|
|
108
|
+
"Should not be an intent payment (same chain and token)"
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
t.end();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("createPaymentBridgeConfig - Payment to Stellar destination", (t) => {
|
|
115
|
+
const config: PaymentBridgeConfig = {
|
|
116
|
+
toChain: rozoStellar.chainId,
|
|
117
|
+
toToken: rozoStellarUSDC.token,
|
|
118
|
+
toAddress: VALID_STELLAR_ADDRESS,
|
|
119
|
+
toUnits: "1", // 1 USDC
|
|
120
|
+
preferredChain: base.chainId,
|
|
121
|
+
preferredTokenAddress: baseUSDC.token,
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const result = createPaymentBridgeConfig(config);
|
|
125
|
+
|
|
126
|
+
t.equal(
|
|
127
|
+
result.preferred.preferredChain,
|
|
128
|
+
String(base.chainId),
|
|
129
|
+
"Preferred chain should be Base"
|
|
130
|
+
);
|
|
131
|
+
t.equal(
|
|
132
|
+
result.preferred.preferredToken,
|
|
133
|
+
"USDC",
|
|
134
|
+
"Preferred token should be USDC"
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
// Destination should be configured for Stellar
|
|
138
|
+
t.equal(
|
|
139
|
+
result.destination.chainId,
|
|
140
|
+
String(rozoStellarUSDC.chainId),
|
|
141
|
+
"Destination chain should be Stellar"
|
|
142
|
+
);
|
|
143
|
+
t.equal(
|
|
144
|
+
result.destination.tokenSymbol,
|
|
145
|
+
rozoStellarUSDC.symbol,
|
|
146
|
+
"Destination token symbol should be Stellar USDC"
|
|
147
|
+
);
|
|
148
|
+
t.equal(
|
|
149
|
+
result.destination.tokenAddress,
|
|
150
|
+
rozoStellarUSDC.token,
|
|
151
|
+
"Destination token address should match Stellar USDC"
|
|
152
|
+
);
|
|
153
|
+
t.equal(
|
|
154
|
+
result.destination.destinationAddress,
|
|
155
|
+
VALID_STELLAR_ADDRESS,
|
|
156
|
+
"Destination address should match Stellar address"
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
t.equal(
|
|
160
|
+
result.isIntentPayment,
|
|
161
|
+
true,
|
|
162
|
+
"Should be an intent payment (Base to Stellar)"
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
t.end();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test("createPaymentBridgeConfig - Payment to Solana destination", (t) => {
|
|
169
|
+
const config: PaymentBridgeConfig = {
|
|
170
|
+
toChain: rozoSolana.chainId,
|
|
171
|
+
toToken: rozoSolanaUSDC.token,
|
|
172
|
+
toAddress: VALID_SOLANA_ADDRESS,
|
|
173
|
+
toUnits: "1", // 1 USDC
|
|
174
|
+
preferredChain: base.chainId,
|
|
175
|
+
preferredTokenAddress: baseUSDC.token,
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const result = createPaymentBridgeConfig(config);
|
|
179
|
+
|
|
180
|
+
t.equal(
|
|
181
|
+
result.preferred.preferredChain,
|
|
182
|
+
String(base.chainId),
|
|
183
|
+
"Preferred chain should be Base"
|
|
184
|
+
);
|
|
185
|
+
t.equal(
|
|
186
|
+
result.preferred.preferredToken,
|
|
187
|
+
"USDC",
|
|
188
|
+
"Preferred token should be USDC"
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
// Destination should be configured for Solana
|
|
192
|
+
t.equal(
|
|
193
|
+
result.destination.chainId,
|
|
194
|
+
String(rozoSolanaUSDC.chainId),
|
|
195
|
+
"Destination chain should be Solana"
|
|
196
|
+
);
|
|
197
|
+
t.equal(
|
|
198
|
+
result.destination.tokenSymbol,
|
|
199
|
+
rozoSolanaUSDC.symbol,
|
|
200
|
+
"Destination token symbol should be Solana USDC"
|
|
201
|
+
);
|
|
202
|
+
t.equal(
|
|
203
|
+
result.destination.tokenAddress,
|
|
204
|
+
rozoSolanaUSDC.token,
|
|
205
|
+
"Destination token address should match Solana USDC"
|
|
206
|
+
);
|
|
207
|
+
t.equal(
|
|
208
|
+
result.destination.destinationAddress,
|
|
209
|
+
VALID_SOLANA_ADDRESS,
|
|
210
|
+
"Destination address should match Solana address"
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
t.equal(
|
|
214
|
+
result.isIntentPayment,
|
|
215
|
+
true,
|
|
216
|
+
"Should be an intent payment (Base to Solana)"
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
t.end();
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test("createPaymentBridgeConfig - Error: Unsupported token", (t) => {
|
|
223
|
+
const config: PaymentBridgeConfig = {
|
|
224
|
+
toChain: base.chainId,
|
|
225
|
+
toToken: "0x0000000000000000000000000000000000000000", // Invalid token
|
|
226
|
+
toAddress: VALID_EVM_ADDRESS,
|
|
227
|
+
toUnits: "1",
|
|
228
|
+
preferredChain: base.chainId,
|
|
229
|
+
preferredTokenAddress: baseUSDC.token,
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
t.throws(
|
|
233
|
+
() => createPaymentBridgeConfig(config),
|
|
234
|
+
/(Unsupported token|or token)/,
|
|
235
|
+
"Should throw error for unsupported token"
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
t.end();
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("createPaymentBridgeConfig - Error: Invalid address for chain", (t) => {
|
|
242
|
+
const config: PaymentBridgeConfig = {
|
|
243
|
+
toChain: base.chainId,
|
|
244
|
+
toToken: baseUSDC.token,
|
|
245
|
+
toAddress: "invalid-address",
|
|
246
|
+
toUnits: "1",
|
|
247
|
+
preferredChain: base.chainId,
|
|
248
|
+
preferredTokenAddress: baseUSDC.token,
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
t.throws(
|
|
252
|
+
() => createPaymentBridgeConfig(config),
|
|
253
|
+
(err: any) => {
|
|
254
|
+
// viem's getAddress throws InvalidAddressError when address is invalid
|
|
255
|
+
// The error will be thrown from validateAddressForChain before the bridge function can catch it
|
|
256
|
+
return (
|
|
257
|
+
err.name === "InvalidAddressError" ||
|
|
258
|
+
err.message?.includes("Address") ||
|
|
259
|
+
err.message?.includes("invalid")
|
|
260
|
+
);
|
|
261
|
+
},
|
|
262
|
+
"Should throw error for invalid address"
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
t.end();
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test("createPaymentBridgeConfig - Error: Unsupported preferred token", (t) => {
|
|
269
|
+
const config: PaymentBridgeConfig = {
|
|
270
|
+
toChain: base.chainId,
|
|
271
|
+
toToken: baseUSDC.token,
|
|
272
|
+
toAddress: VALID_EVM_ADDRESS,
|
|
273
|
+
toUnits: "1",
|
|
274
|
+
preferredChain: polygon.chainId,
|
|
275
|
+
preferredTokenAddress: "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", // Truly invalid token address
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
t.throws(
|
|
279
|
+
() => createPaymentBridgeConfig(config),
|
|
280
|
+
/Unknown token/,
|
|
281
|
+
"Should throw error for unsupported preferred token"
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
t.end();
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
test("createPaymentBridgeConfig - Error: Unsupported chain or token", (t) => {
|
|
288
|
+
const config: PaymentBridgeConfig = {
|
|
289
|
+
toChain: 99999, // Unsupported chain
|
|
290
|
+
toToken: baseUSDC.token,
|
|
291
|
+
toAddress: VALID_EVM_ADDRESS,
|
|
292
|
+
toUnits: "1",
|
|
293
|
+
preferredChain: base.chainId,
|
|
294
|
+
preferredTokenAddress: baseUSDC.token,
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
t.throws(
|
|
298
|
+
() => createPaymentBridgeConfig(config),
|
|
299
|
+
/Unknown chainId/,
|
|
300
|
+
"Should throw error for unsupported chain"
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
t.end();
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test("createPaymentBridgeConfig - Intent payment detection: different chain, same token", (t) => {
|
|
307
|
+
const config: PaymentBridgeConfig = {
|
|
308
|
+
toChain: base.chainId,
|
|
309
|
+
toToken: baseUSDC.token,
|
|
310
|
+
toAddress: VALID_EVM_ADDRESS,
|
|
311
|
+
toUnits: "1",
|
|
312
|
+
preferredChain: polygon.chainId,
|
|
313
|
+
preferredTokenAddress: polygonUSDC.token,
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
const result = createPaymentBridgeConfig(config);
|
|
317
|
+
|
|
318
|
+
t.equal(
|
|
319
|
+
result.isIntentPayment,
|
|
320
|
+
true,
|
|
321
|
+
"Should be intent payment when chains differ"
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
t.end();
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
test("createPaymentBridgeConfig - Intent payment detection: same chain, different token", (t) => {
|
|
328
|
+
// This test assumes there are different tokens on the same chain
|
|
329
|
+
// For Base, we'll use the same token but the logic should still work
|
|
330
|
+
const config: PaymentBridgeConfig = {
|
|
331
|
+
toChain: base.chainId,
|
|
332
|
+
toToken: baseUSDC.token,
|
|
333
|
+
toAddress: VALID_EVM_ADDRESS,
|
|
334
|
+
toUnits: "1",
|
|
335
|
+
preferredChain: base.chainId,
|
|
336
|
+
preferredTokenAddress: baseUSDC.token,
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const result = createPaymentBridgeConfig(config);
|
|
340
|
+
|
|
341
|
+
// When same chain and token, preferredTokenAddress will be set but
|
|
342
|
+
// the comparison checks preferredToken (symbol) vs toToken (address)
|
|
343
|
+
// So this might still be false if symbols match
|
|
344
|
+
t.equal(
|
|
345
|
+
result.isIntentPayment,
|
|
346
|
+
false,
|
|
347
|
+
"Should not be intent payment when same chain and token"
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
t.end();
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
test("createPaymentBridgeConfig - Large amount units", (t) => {
|
|
354
|
+
const config: PaymentBridgeConfig = {
|
|
355
|
+
toChain: base.chainId,
|
|
356
|
+
toToken: baseUSDC.token,
|
|
357
|
+
toAddress: VALID_EVM_ADDRESS,
|
|
358
|
+
toUnits: "1000000", // 1 million USDC
|
|
359
|
+
preferredChain: polygon.chainId,
|
|
360
|
+
preferredTokenAddress: polygonUSDC.token,
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const result = createPaymentBridgeConfig(config);
|
|
364
|
+
|
|
365
|
+
t.equal(
|
|
366
|
+
result.destination.amountUnits,
|
|
367
|
+
"1000000",
|
|
368
|
+
"Should handle large amount units correctly"
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
t.end();
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
test("createPaymentBridgeConfig - Zero amount units", (t) => {
|
|
375
|
+
const config: PaymentBridgeConfig = {
|
|
376
|
+
toChain: base.chainId,
|
|
377
|
+
toToken: baseUSDC.token,
|
|
378
|
+
toAddress: VALID_EVM_ADDRESS,
|
|
379
|
+
toUnits: "0",
|
|
380
|
+
preferredChain: base.chainId,
|
|
381
|
+
preferredTokenAddress: baseUSDC.token,
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
const result = createPaymentBridgeConfig(config);
|
|
385
|
+
|
|
386
|
+
t.equal(
|
|
387
|
+
result.destination.amountUnits,
|
|
388
|
+
"0",
|
|
389
|
+
"Should handle zero amount units correctly"
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
t.end();
|
|
393
|
+
});
|