@luxfi/exchange 0.1.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/dist/bridge/__tests__/use-private-teleport.test.d.ts +2 -0
- package/dist/bridge/__tests__/use-private-teleport.test.d.ts.map +1 -0
- package/dist/bridge/__tests__/use-private-teleport.test.js +272 -0
- package/dist/bridge/cross-chain-store.d.ts +57 -0
- package/dist/bridge/cross-chain-store.d.ts.map +1 -0
- package/dist/bridge/cross-chain-store.js +158 -0
- package/dist/bridge/index.d.ts +78 -0
- package/dist/bridge/index.d.ts.map +1 -0
- package/dist/bridge/index.js +79 -0
- package/dist/bridge/private-teleport-types.d.ts +634 -0
- package/dist/bridge/private-teleport-types.d.ts.map +1 -0
- package/dist/bridge/private-teleport-types.js +308 -0
- package/dist/bridge/types.d.ts +84 -0
- package/dist/bridge/types.d.ts.map +1 -0
- package/dist/bridge/types.js +37 -0
- package/dist/bridge/use-cross-chain-mint.d.ts +34 -0
- package/dist/bridge/use-cross-chain-mint.d.ts.map +1 -0
- package/dist/bridge/use-cross-chain-mint.js +228 -0
- package/dist/bridge/use-private-teleport.d.ts +69 -0
- package/dist/bridge/use-private-teleport.d.ts.map +1 -0
- package/dist/bridge/use-private-teleport.js +666 -0
- package/dist/chains/index.d.ts +6 -0
- package/dist/chains/index.d.ts.map +1 -0
- package/dist/chains/index.js +6 -0
- package/dist/chains/lux.d.ts +508 -0
- package/dist/chains/lux.d.ts.map +1 -0
- package/dist/chains/lux.js +131 -0
- package/dist/contracts/abis/dex-swap-router.d.ts +137 -0
- package/dist/contracts/abis/dex-swap-router.d.ts.map +1 -0
- package/dist/contracts/abis/dex-swap-router.js +95 -0
- package/dist/contracts/abis/erc20.d.ts +136 -0
- package/dist/contracts/abis/erc20.d.ts.map +1 -0
- package/dist/contracts/abis/erc20.js +96 -0
- package/dist/contracts/abis/index.d.ts +15 -0
- package/dist/contracts/abis/index.d.ts.map +1 -0
- package/dist/contracts/abis/index.js +15 -0
- package/dist/contracts/abis/nft-position-manager.d.ts +235 -0
- package/dist/contracts/abis/nft-position-manager.d.ts.map +1 -0
- package/dist/contracts/abis/nft-position-manager.js +146 -0
- package/dist/contracts/abis/pool-manager.d.ts +315 -0
- package/dist/contracts/abis/pool-manager.d.ts.map +1 -0
- package/dist/contracts/abis/pool-manager.js +191 -0
- package/dist/contracts/abis/quoter-v2.d.ts +103 -0
- package/dist/contracts/abis/quoter-v2.d.ts.map +1 -0
- package/dist/contracts/abis/quoter-v2.js +68 -0
- package/dist/contracts/abis/swap-router.d.ts +119 -0
- package/dist/contracts/abis/swap-router.d.ts.map +1 -0
- package/dist/contracts/abis/swap-router.js +75 -0
- package/dist/contracts/abis/uniswap-v2-factory.d.ts +75 -0
- package/dist/contracts/abis/uniswap-v2-factory.d.ts.map +1 -0
- package/dist/contracts/abis/uniswap-v2-factory.js +49 -0
- package/dist/contracts/abis/uniswap-v2-pair.d.ts +119 -0
- package/dist/contracts/abis/uniswap-v2-pair.d.ts.map +1 -0
- package/dist/contracts/abis/uniswap-v2-pair.js +85 -0
- package/dist/contracts/abis/uniswap-v2-router.d.ts +249 -0
- package/dist/contracts/abis/uniswap-v2-router.d.ts.map +1 -0
- package/dist/contracts/abis/uniswap-v2-router.js +146 -0
- package/dist/contracts/abis/uniswap-v3-factory.d.ts +77 -0
- package/dist/contracts/abis/uniswap-v3-factory.d.ts.map +1 -0
- package/dist/contracts/abis/uniswap-v3-factory.js +45 -0
- package/dist/contracts/abis/uniswap-v3-pool.d.ts +128 -0
- package/dist/contracts/abis/uniswap-v3-pool.d.ts.map +1 -0
- package/dist/contracts/abis/uniswap-v3-pool.js +81 -0
- package/dist/contracts/addresses.d.ts +141 -0
- package/dist/contracts/addresses.d.ts.map +1 -0
- package/dist/contracts/addresses.js +108 -0
- package/dist/contracts/index.d.ts +6 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +5 -0
- package/dist/dex/balance-delta.d.ts +27 -0
- package/dist/dex/balance-delta.d.ts.map +1 -0
- package/dist/dex/balance-delta.js +45 -0
- package/dist/dex/index.d.ts +7 -0
- package/dist/dex/index.d.ts.map +1 -0
- package/dist/dex/index.js +6 -0
- package/dist/dex/pool-key.d.ts +19 -0
- package/dist/dex/pool-key.d.ts.map +1 -0
- package/dist/dex/pool-key.js +44 -0
- package/dist/dex/types.d.ts +71 -0
- package/dist/dex/types.d.ts.map +1 -0
- package/dist/dex/types.js +28 -0
- package/dist/hooks/index.d.ts +10 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +9 -0
- package/dist/hooks/use-pools.d.ts +24 -0
- package/dist/hooks/use-pools.d.ts.map +1 -0
- package/dist/hooks/use-pools.js +85 -0
- package/dist/hooks/use-positions.d.ts +17 -0
- package/dist/hooks/use-positions.d.ts.map +1 -0
- package/dist/hooks/use-positions.js +65 -0
- package/dist/hooks/use-swap-quote.d.ts +19 -0
- package/dist/hooks/use-swap-quote.d.ts.map +1 -0
- package/dist/hooks/use-swap-quote.js +54 -0
- package/dist/hooks/use-swap.d.ts +22 -0
- package/dist/hooks/use-swap.d.ts.map +1 -0
- package/dist/hooks/use-swap.js +46 -0
- package/dist/hooks/use-token-allowance.d.ts +27 -0
- package/dist/hooks/use-token-allowance.d.ts.map +1 -0
- package/dist/hooks/use-token-allowance.js +59 -0
- package/dist/hooks/use-token-balance.d.ts +17 -0
- package/dist/hooks/use-token-balance.d.ts.map +1 -0
- package/dist/hooks/use-token-balance.js +58 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/stores/index.d.ts +7 -0
- package/dist/stores/index.d.ts.map +1 -0
- package/dist/stores/index.js +6 -0
- package/dist/stores/settings-store.d.ts +25 -0
- package/dist/stores/settings-store.d.ts.map +1 -0
- package/dist/stores/settings-store.js +16 -0
- package/dist/stores/swap-store.d.ts +38 -0
- package/dist/stores/swap-store.d.ts.map +1 -0
- package/dist/stores/swap-store.js +58 -0
- package/dist/stores/token-store.d.ts +21 -0
- package/dist/stores/token-store.d.ts.map +1 -0
- package/dist/stores/token-store.js +32 -0
- package/dist/tokens/index.d.ts +65 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +185 -0
- package/package.json +78 -0
- package/src/chains/index.ts +21 -0
- package/src/chains/lux.ts +141 -0
- package/src/contracts/abis/dex-swap-router.ts +98 -0
- package/src/contracts/abis/erc20.ts +96 -0
- package/src/contracts/abis/index.ts +17 -0
- package/src/contracts/abis/nft-position-manager.ts +146 -0
- package/src/contracts/abis/pool-manager.ts +198 -0
- package/src/contracts/abis/quoter-v2.ts +68 -0
- package/src/contracts/abis/swap-router.ts +75 -0
- package/src/contracts/abis/uniswap-v2-factory.ts +49 -0
- package/src/contracts/abis/uniswap-v2-pair.ts +85 -0
- package/src/contracts/abis/uniswap-v2-router.ts +146 -0
- package/src/contracts/abis/uniswap-v3-factory.ts +45 -0
- package/src/contracts/abis/uniswap-v3-pool.ts +81 -0
- package/src/contracts/addresses.ts +128 -0
- package/src/contracts/index.ts +14 -0
- package/src/dex/balance-delta.ts +52 -0
- package/src/dex/index.ts +7 -0
- package/src/dex/pool-key.ts +62 -0
- package/src/dex/types.ts +87 -0
- package/src/hooks/index.ts +10 -0
- package/src/hooks/use-pools.ts +116 -0
- package/src/hooks/use-positions.ts +90 -0
- package/src/hooks/use-swap-quote.ts +81 -0
- package/src/hooks/use-swap.ts +64 -0
- package/src/hooks/use-token-allowance.ts +74 -0
- package/src/hooks/use-token-balance.ts +71 -0
- package/src/index.ts +31 -0
- package/src/stores/index.ts +7 -0
- package/src/stores/settings-store.ts +54 -0
- package/src/stores/swap-store.ts +112 -0
- package/src/stores/token-store.ts +62 -0
- package/src/tokens/index.ts +220 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-private-teleport.test.d.ts","sourceRoot":"","sources":["../../../src/bridge/__tests__/use-private-teleport.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { TeleportState } from '../private-teleport-types';
|
|
3
|
+
// Test that types are correctly exported and usable
|
|
4
|
+
describe('PrivateTeleport Types', () => {
|
|
5
|
+
describe('TeleportState enum', () => {
|
|
6
|
+
it('should have correct numeric values', () => {
|
|
7
|
+
expect(TeleportState.INITIATED).toBe(0);
|
|
8
|
+
expect(TeleportState.SHIELDED).toBe(1);
|
|
9
|
+
expect(TeleportState.SWAP_COMPLETE).toBe(2);
|
|
10
|
+
expect(TeleportState.EXPORTED).toBe(3);
|
|
11
|
+
expect(TeleportState.COMPLETED).toBe(4);
|
|
12
|
+
expect(TeleportState.CANCELLED).toBe(5);
|
|
13
|
+
expect(TeleportState.EXPIRED).toBe(6);
|
|
14
|
+
});
|
|
15
|
+
it('should have all expected states', () => {
|
|
16
|
+
const states = Object.values(TeleportState).filter(v => typeof v === 'number');
|
|
17
|
+
expect(states).toHaveLength(7);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe('ZNote type', () => {
|
|
21
|
+
it('should allow valid ZNote creation', () => {
|
|
22
|
+
const znote = {
|
|
23
|
+
commitment: '0x1234567890abcdef',
|
|
24
|
+
nullifier: '0xfedcba0987654321',
|
|
25
|
+
encryptedAmount: '0xencrypted',
|
|
26
|
+
owner: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
|
|
27
|
+
};
|
|
28
|
+
expect(znote.commitment).toBe('0x1234567890abcdef');
|
|
29
|
+
expect(znote.nullifier).toBe('0xfedcba0987654321');
|
|
30
|
+
expect(znote.encryptedAmount).toBe('0xencrypted');
|
|
31
|
+
expect(znote.owner).toBe('0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266');
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe('TeleportInfo type', () => {
|
|
35
|
+
it('should allow valid TeleportInfo creation', () => {
|
|
36
|
+
const info = {
|
|
37
|
+
id: '0xteleportId',
|
|
38
|
+
sourceChain: 1,
|
|
39
|
+
destChain: 2,
|
|
40
|
+
sourceToken: '0xsourceToken',
|
|
41
|
+
destToken: '0xdestToken',
|
|
42
|
+
sender: '0xsender',
|
|
43
|
+
recipient: '0xrecipient',
|
|
44
|
+
amount: BigInt(1000000000000000000),
|
|
45
|
+
state: TeleportState.INITIATED,
|
|
46
|
+
createdAt: BigInt(Date.now()),
|
|
47
|
+
deadline: BigInt(Date.now() + 3600000),
|
|
48
|
+
};
|
|
49
|
+
expect(info.state).toBe(TeleportState.INITIATED);
|
|
50
|
+
expect(info.sourceChain).toBe(1);
|
|
51
|
+
expect(info.destChain).toBe(2);
|
|
52
|
+
});
|
|
53
|
+
it('should handle optional znote field', () => {
|
|
54
|
+
const infoWithZNote = {
|
|
55
|
+
id: '0xteleportId',
|
|
56
|
+
sourceChain: 1,
|
|
57
|
+
destChain: 2,
|
|
58
|
+
sourceToken: '0xsourceToken',
|
|
59
|
+
destToken: '0xdestToken',
|
|
60
|
+
sender: '0xsender',
|
|
61
|
+
recipient: '0xrecipient',
|
|
62
|
+
amount: BigInt(1000000000000000000),
|
|
63
|
+
state: TeleportState.SHIELDED,
|
|
64
|
+
createdAt: BigInt(Date.now()),
|
|
65
|
+
deadline: BigInt(Date.now() + 3600000),
|
|
66
|
+
znote: {
|
|
67
|
+
commitment: '0xcommitment',
|
|
68
|
+
nullifier: '0xnullifier',
|
|
69
|
+
encryptedAmount: '0xencrypted',
|
|
70
|
+
owner: '0xowner',
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
expect(infoWithZNote.znote).toBeDefined();
|
|
74
|
+
expect(infoWithZNote.znote?.commitment).toBe('0xcommitment');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe('PrivateTeleportConfig type', () => {
|
|
78
|
+
it('should allow valid config creation', () => {
|
|
79
|
+
const config = {
|
|
80
|
+
sourceChainId: 1,
|
|
81
|
+
destChainId: 2,
|
|
82
|
+
sourceToken: '0xsourceToken',
|
|
83
|
+
destToken: '0xdestToken',
|
|
84
|
+
amount: BigInt(1000000000000000000),
|
|
85
|
+
recipient: '0xrecipient',
|
|
86
|
+
slippageTolerance: 50, // 0.5%
|
|
87
|
+
deadline: BigInt(Date.now() + 3600000),
|
|
88
|
+
};
|
|
89
|
+
expect(config.sourceChainId).toBe(1);
|
|
90
|
+
expect(config.destChainId).toBe(2);
|
|
91
|
+
expect(config.slippageTolerance).toBe(50);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe('TeleportState transitions', () => {
|
|
96
|
+
it('should follow valid state progression', () => {
|
|
97
|
+
// Valid progression: INITIATED -> SHIELDED -> SWAP_COMPLETE -> EXPORTED -> COMPLETED
|
|
98
|
+
const validProgression = [
|
|
99
|
+
TeleportState.INITIATED,
|
|
100
|
+
TeleportState.SHIELDED,
|
|
101
|
+
TeleportState.SWAP_COMPLETE,
|
|
102
|
+
TeleportState.EXPORTED,
|
|
103
|
+
TeleportState.COMPLETED,
|
|
104
|
+
];
|
|
105
|
+
for (let i = 0; i < validProgression.length - 1; i++) {
|
|
106
|
+
expect(validProgression[i]).toBeLessThan(validProgression[i + 1]);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
it('should identify terminal states', () => {
|
|
110
|
+
const terminalStates = [TeleportState.COMPLETED, TeleportState.CANCELLED, TeleportState.EXPIRED];
|
|
111
|
+
terminalStates.forEach((state) => {
|
|
112
|
+
expect(state).toBeGreaterThanOrEqual(TeleportState.COMPLETED);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
it('should identify cancellable states', () => {
|
|
116
|
+
const cancellableStates = [TeleportState.INITIATED, TeleportState.SHIELDED];
|
|
117
|
+
cancellableStates.forEach((state) => {
|
|
118
|
+
expect(state).toBeLessThan(TeleportState.SWAP_COMPLETE);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
describe('Amount calculations', () => {
|
|
123
|
+
it('should handle BigInt amounts correctly', () => {
|
|
124
|
+
const oneEther = BigInt(1e18);
|
|
125
|
+
const halfEther = BigInt(5e17);
|
|
126
|
+
expect(oneEther + halfEther).toBe(BigInt(15e17));
|
|
127
|
+
expect(oneEther - halfEther).toBe(halfEther);
|
|
128
|
+
expect(oneEther / BigInt(2)).toBe(halfEther);
|
|
129
|
+
});
|
|
130
|
+
it('should calculate slippage correctly', () => {
|
|
131
|
+
const amount = BigInt(1000000000000000000); // 1 ETH
|
|
132
|
+
const slippageBps = 50; // 0.5%
|
|
133
|
+
const minOutput = amount - (amount * BigInt(slippageBps)) / BigInt(10000);
|
|
134
|
+
const expectedMinOutput = BigInt(995000000000000000); // 0.995 ETH
|
|
135
|
+
expect(minOutput).toBe(expectedMinOutput);
|
|
136
|
+
});
|
|
137
|
+
it('should handle zero amounts', () => {
|
|
138
|
+
const zero = BigInt(0);
|
|
139
|
+
expect(zero).toBe(BigInt(0));
|
|
140
|
+
expect(zero + BigInt(100)).toBe(BigInt(100));
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
describe('Address validation helpers', () => {
|
|
144
|
+
it('should validate Ethereum addresses', () => {
|
|
145
|
+
const validAddress = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266';
|
|
146
|
+
expect(validAddress.length).toBe(42);
|
|
147
|
+
expect(validAddress.startsWith('0x')).toBe(true);
|
|
148
|
+
expect(/^0x[a-fA-F0-9]{40}$/.test(validAddress)).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
it('should reject invalid addresses', () => {
|
|
151
|
+
const invalidAddresses = ['0x123', 'notanaddress', '0x' + 'g'.repeat(40)];
|
|
152
|
+
invalidAddresses.forEach((addr) => {
|
|
153
|
+
expect(/^0x[a-fA-F0-9]{40}$/.test(addr)).toBe(false);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
it('should handle checksummed addresses', () => {
|
|
157
|
+
const checksummed = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266';
|
|
158
|
+
const lowercase = checksummed.toLowerCase();
|
|
159
|
+
expect(checksummed.toLowerCase()).toBe(lowercase);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
describe('Chain ID validation', () => {
|
|
163
|
+
const supportedChains = [1, 96369, 200200, 200201]; // Mainnet, Lux, Zoo, Zootest
|
|
164
|
+
it('should identify supported chains', () => {
|
|
165
|
+
supportedChains.forEach((chainId) => {
|
|
166
|
+
expect(chainId).toBeGreaterThan(0);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
it('should reject invalid chain IDs', () => {
|
|
170
|
+
const invalidChains = [0, -1];
|
|
171
|
+
invalidChains.forEach((chainId) => {
|
|
172
|
+
expect(chainId).toBeLessThanOrEqual(0);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
describe('Deadline handling', () => {
|
|
177
|
+
it('should calculate valid deadline', () => {
|
|
178
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
179
|
+
const oneHourFromNow = now + BigInt(3600);
|
|
180
|
+
expect(oneHourFromNow).toBeGreaterThan(now);
|
|
181
|
+
});
|
|
182
|
+
it('should identify expired deadlines', () => {
|
|
183
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
184
|
+
const oneHourAgo = now - BigInt(3600);
|
|
185
|
+
expect(oneHourAgo).toBeLessThan(now);
|
|
186
|
+
});
|
|
187
|
+
it('should handle deadline extension', () => {
|
|
188
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
189
|
+
const deadline = now + BigInt(3600);
|
|
190
|
+
const extendedDeadline = deadline + BigInt(1800); // Add 30 minutes
|
|
191
|
+
expect(extendedDeadline).toBeGreaterThan(deadline);
|
|
192
|
+
expect(extendedDeadline - deadline).toBe(BigInt(1800));
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
describe('Error scenarios', () => {
|
|
196
|
+
it('should handle insufficient balance error', () => {
|
|
197
|
+
const balance = BigInt(1e18);
|
|
198
|
+
const requested = BigInt(2e18);
|
|
199
|
+
expect(balance < requested).toBe(true);
|
|
200
|
+
});
|
|
201
|
+
it('should handle slippage exceeded error', () => {
|
|
202
|
+
const expectedOutput = BigInt(1e18); // 1 ETH expected
|
|
203
|
+
const actualOutput = BigInt(9e17); // 0.9 ETH received (10% slippage)
|
|
204
|
+
const minAcceptable = BigInt(95e16); // 0.95 ETH (5% slippage tolerance)
|
|
205
|
+
// Actual output is below minimum acceptable, so slippage exceeded
|
|
206
|
+
expect(actualOutput < minAcceptable).toBe(true);
|
|
207
|
+
expect(actualOutput < expectedOutput).toBe(true);
|
|
208
|
+
});
|
|
209
|
+
it('should handle deadline passed error', () => {
|
|
210
|
+
const now = Math.floor(Date.now() / 1000);
|
|
211
|
+
const expiredDeadline = now - 3600;
|
|
212
|
+
expect(expiredDeadline < now).toBe(true);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
describe('Privacy features', () => {
|
|
216
|
+
it('should generate unique commitments', () => {
|
|
217
|
+
// Mock commitment generation - in reality uses keccak256(secret + value)
|
|
218
|
+
const commitment1 = '0x' + '1'.repeat(64);
|
|
219
|
+
const commitment2 = '0x' + '2'.repeat(64);
|
|
220
|
+
expect(commitment1).not.toBe(commitment2);
|
|
221
|
+
expect(commitment1.length).toBe(66); // 0x + 64 hex chars
|
|
222
|
+
});
|
|
223
|
+
it('should verify nullifier uniqueness', () => {
|
|
224
|
+
const nullifiers = new Set();
|
|
225
|
+
const nullifier1 = '0x' + 'a'.repeat(64);
|
|
226
|
+
const nullifier2 = '0x' + 'b'.repeat(64);
|
|
227
|
+
nullifiers.add(nullifier1);
|
|
228
|
+
expect(nullifiers.has(nullifier1)).toBe(true);
|
|
229
|
+
expect(nullifiers.has(nullifier2)).toBe(false);
|
|
230
|
+
});
|
|
231
|
+
it('should handle encrypted amounts', () => {
|
|
232
|
+
// FHE encrypted values are opaque strings
|
|
233
|
+
const encryptedAmount = '0x' + 'encrypted_data'.padEnd(128, '0');
|
|
234
|
+
expect(encryptedAmount.startsWith('0x')).toBe(true);
|
|
235
|
+
expect(encryptedAmount.length).toBeGreaterThan(2);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
describe('Swap routing', () => {
|
|
239
|
+
it('should calculate price impact', () => {
|
|
240
|
+
const inputAmount = BigInt(1e18);
|
|
241
|
+
const outputAmount = BigInt(998e15); // 0.998 ETH equivalent
|
|
242
|
+
const priceImpactBps = ((inputAmount - outputAmount) * BigInt(10000)) / inputAmount;
|
|
243
|
+
expect(priceImpactBps).toBe(BigInt(20)); // 0.2%
|
|
244
|
+
});
|
|
245
|
+
it('should select optimal route', () => {
|
|
246
|
+
const routes = [
|
|
247
|
+
{ output: BigInt(990e15), path: ['A', 'B'] },
|
|
248
|
+
{ output: BigInt(995e15), path: ['A', 'C', 'B'] },
|
|
249
|
+
{ output: BigInt(998e15), path: ['A', 'B'] },
|
|
250
|
+
];
|
|
251
|
+
const bestRoute = routes.reduce((best, current) => (current.output > best.output ? current : best));
|
|
252
|
+
expect(bestRoute.output).toBe(BigInt(998e15));
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
describe('Cross-chain message verification', () => {
|
|
256
|
+
it('should verify Warp message format', () => {
|
|
257
|
+
const warpMessage = {
|
|
258
|
+
sourceChainId: 1,
|
|
259
|
+
destChainId: 96369,
|
|
260
|
+
payload: '0x' + 'data'.padEnd(64, '0'),
|
|
261
|
+
signature: '0x' + 'sig'.padEnd(130, '0'),
|
|
262
|
+
};
|
|
263
|
+
expect(warpMessage.sourceChainId).toBe(1);
|
|
264
|
+
expect(warpMessage.destChainId).toBe(96369);
|
|
265
|
+
expect(warpMessage.payload.startsWith('0x')).toBe(true);
|
|
266
|
+
});
|
|
267
|
+
it('should validate BLS signature length', () => {
|
|
268
|
+
// BLS signatures are 96 bytes = 192 hex chars
|
|
269
|
+
const blsSignature = '0x' + '0'.repeat(192);
|
|
270
|
+
expect(blsSignature.length).toBe(194); // 0x + 192 hex chars
|
|
271
|
+
});
|
|
272
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zustand store for cross-chain mint operations
|
|
3
|
+
*/
|
|
4
|
+
import type { CrossChainMintRequest, CrossChainMintState, CrossChainMintStatus } from './types';
|
|
5
|
+
interface PendingMint extends CrossChainMintRequest {
|
|
6
|
+
state: CrossChainMintState;
|
|
7
|
+
}
|
|
8
|
+
export interface CrossChainStore {
|
|
9
|
+
/** Currently active mints by swap ID */
|
|
10
|
+
pendingMints: Record<string, PendingMint>;
|
|
11
|
+
/** Most recent completed mints (for history) */
|
|
12
|
+
recentMints: PendingMint[];
|
|
13
|
+
/** Maximum number of recent mints to keep */
|
|
14
|
+
maxRecentMints: number;
|
|
15
|
+
initiateMint: (request: CrossChainMintRequest) => string;
|
|
16
|
+
updateMintStatus: (swapId: string, status: CrossChainMintStatus) => void;
|
|
17
|
+
updateMintTxHash: (swapId: string, field: 'sourceTxHash' | 'mintTxHash' | 'swapTxHash', hash: string) => void;
|
|
18
|
+
completeMint: (swapId: string) => void;
|
|
19
|
+
failMint: (swapId: string, error: string) => void;
|
|
20
|
+
cancelMint: (swapId: string) => void;
|
|
21
|
+
clearPendingMint: (swapId: string) => void;
|
|
22
|
+
getPendingMint: (swapId: string) => PendingMint | undefined;
|
|
23
|
+
getActiveMints: () => PendingMint[];
|
|
24
|
+
}
|
|
25
|
+
export declare const useCrossChainStore: import("zustand").UseBoundStore<Omit<Omit<import("zustand").StoreApi<CrossChainStore>, "setState" | "devtools"> & {
|
|
26
|
+
setState(partial: CrossChainStore | Partial<CrossChainStore> | ((state: CrossChainStore) => CrossChainStore | Partial<CrossChainStore>), replace?: false | undefined, action?: (string | {
|
|
27
|
+
[x: string]: unknown;
|
|
28
|
+
[x: number]: unknown;
|
|
29
|
+
[x: symbol]: unknown;
|
|
30
|
+
type: string;
|
|
31
|
+
}) | undefined): void;
|
|
32
|
+
setState(state: CrossChainStore | ((state: CrossChainStore) => CrossChainStore), replace: true, action?: (string | {
|
|
33
|
+
[x: string]: unknown;
|
|
34
|
+
[x: number]: unknown;
|
|
35
|
+
[x: symbol]: unknown;
|
|
36
|
+
type: string;
|
|
37
|
+
}) | undefined): void;
|
|
38
|
+
devtools: {
|
|
39
|
+
cleanup: () => void;
|
|
40
|
+
};
|
|
41
|
+
}, "persist"> & {
|
|
42
|
+
persist: {
|
|
43
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<CrossChainStore, {
|
|
44
|
+
recentMints: PendingMint[];
|
|
45
|
+
}>>) => void;
|
|
46
|
+
clearStorage: () => void;
|
|
47
|
+
rehydrate: () => Promise<void> | void;
|
|
48
|
+
hasHydrated: () => boolean;
|
|
49
|
+
onHydrate: (fn: (state: CrossChainStore) => void) => () => void;
|
|
50
|
+
onFinishHydration: (fn: (state: CrossChainStore) => void) => () => void;
|
|
51
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<CrossChainStore, {
|
|
52
|
+
recentMints: PendingMint[];
|
|
53
|
+
}>>;
|
|
54
|
+
};
|
|
55
|
+
}>;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=cross-chain-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-chain-store.d.ts","sourceRoot":"","sources":["../../src/bridge/cross-chain-store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAE/F,UAAU,WAAY,SAAQ,qBAAqB;IACjD,KAAK,EAAE,mBAAmB,CAAA;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACzC,gDAAgD;IAChD,WAAW,EAAE,WAAW,EAAE,CAAA;IAC1B,6CAA6C;IAC7C,cAAc,EAAE,MAAM,CAAA;IAGtB,YAAY,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,MAAM,CAAA;IACxD,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAA;IACxE,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,YAAY,GAAG,YAAY,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7G,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjD,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAA;IAC3D,cAAc,EAAE,MAAM,WAAW,EAAE,CAAA;CACpC;AASD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0K9B,CAAA"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zustand store for cross-chain mint operations
|
|
3
|
+
*/
|
|
4
|
+
import { create } from 'zustand';
|
|
5
|
+
import { devtools, persist } from 'zustand/middleware';
|
|
6
|
+
// Generate a random swap ID
|
|
7
|
+
function generateSwapId() {
|
|
8
|
+
const bytes = new Uint8Array(32);
|
|
9
|
+
crypto.getRandomValues(bytes);
|
|
10
|
+
return '0x' + Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
11
|
+
}
|
|
12
|
+
export const useCrossChainStore = create()(devtools(persist((set, get) => ({
|
|
13
|
+
pendingMints: {},
|
|
14
|
+
recentMints: [],
|
|
15
|
+
maxRecentMints: 20,
|
|
16
|
+
initiateMint: (request) => {
|
|
17
|
+
const swapId = generateSwapId();
|
|
18
|
+
const now = Date.now();
|
|
19
|
+
const pendingMint = {
|
|
20
|
+
...request,
|
|
21
|
+
state: {
|
|
22
|
+
swapId: swapId,
|
|
23
|
+
status: 'initiating',
|
|
24
|
+
sourceTxHash: null,
|
|
25
|
+
mintTxHash: null,
|
|
26
|
+
swapTxHash: null,
|
|
27
|
+
error: null,
|
|
28
|
+
startedAt: now,
|
|
29
|
+
completedAt: null,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
set((state) => ({
|
|
33
|
+
pendingMints: {
|
|
34
|
+
...state.pendingMints,
|
|
35
|
+
[swapId]: pendingMint,
|
|
36
|
+
},
|
|
37
|
+
}));
|
|
38
|
+
return swapId;
|
|
39
|
+
},
|
|
40
|
+
updateMintStatus: (swapId, status) => {
|
|
41
|
+
set((state) => {
|
|
42
|
+
const mint = state.pendingMints[swapId];
|
|
43
|
+
if (!mint)
|
|
44
|
+
return state;
|
|
45
|
+
return {
|
|
46
|
+
pendingMints: {
|
|
47
|
+
...state.pendingMints,
|
|
48
|
+
[swapId]: {
|
|
49
|
+
...mint,
|
|
50
|
+
state: {
|
|
51
|
+
...mint.state,
|
|
52
|
+
status,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
updateMintTxHash: (swapId, field, hash) => {
|
|
60
|
+
set((state) => {
|
|
61
|
+
const mint = state.pendingMints[swapId];
|
|
62
|
+
if (!mint)
|
|
63
|
+
return state;
|
|
64
|
+
return {
|
|
65
|
+
pendingMints: {
|
|
66
|
+
...state.pendingMints,
|
|
67
|
+
[swapId]: {
|
|
68
|
+
...mint,
|
|
69
|
+
state: {
|
|
70
|
+
...mint.state,
|
|
71
|
+
[field]: hash,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
completeMint: (swapId) => {
|
|
79
|
+
set((state) => {
|
|
80
|
+
const mint = state.pendingMints[swapId];
|
|
81
|
+
if (!mint)
|
|
82
|
+
return state;
|
|
83
|
+
const completedMint = {
|
|
84
|
+
...mint,
|
|
85
|
+
state: {
|
|
86
|
+
...mint.state,
|
|
87
|
+
status: 'complete',
|
|
88
|
+
completedAt: Date.now(),
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
const { [swapId]: _, ...remainingPending } = state.pendingMints;
|
|
92
|
+
const newRecent = [completedMint, ...state.recentMints].slice(0, state.maxRecentMints);
|
|
93
|
+
return {
|
|
94
|
+
pendingMints: remainingPending,
|
|
95
|
+
recentMints: newRecent,
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
failMint: (swapId, error) => {
|
|
100
|
+
set((state) => {
|
|
101
|
+
const mint = state.pendingMints[swapId];
|
|
102
|
+
if (!mint)
|
|
103
|
+
return state;
|
|
104
|
+
return {
|
|
105
|
+
pendingMints: {
|
|
106
|
+
...state.pendingMints,
|
|
107
|
+
[swapId]: {
|
|
108
|
+
...mint,
|
|
109
|
+
state: {
|
|
110
|
+
...mint.state,
|
|
111
|
+
status: 'failed',
|
|
112
|
+
error,
|
|
113
|
+
completedAt: Date.now(),
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
cancelMint: (swapId) => {
|
|
121
|
+
set((state) => {
|
|
122
|
+
const mint = state.pendingMints[swapId];
|
|
123
|
+
if (!mint)
|
|
124
|
+
return state;
|
|
125
|
+
return {
|
|
126
|
+
pendingMints: {
|
|
127
|
+
...state.pendingMints,
|
|
128
|
+
[swapId]: {
|
|
129
|
+
...mint,
|
|
130
|
+
state: {
|
|
131
|
+
...mint.state,
|
|
132
|
+
status: 'cancelled',
|
|
133
|
+
completedAt: Date.now(),
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
clearPendingMint: (swapId) => {
|
|
141
|
+
set((state) => {
|
|
142
|
+
const { [swapId]: _, ...remainingPending } = state.pendingMints;
|
|
143
|
+
return { pendingMints: remainingPending };
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
getPendingMint: (swapId) => {
|
|
147
|
+
return get().pendingMints[swapId];
|
|
148
|
+
},
|
|
149
|
+
getActiveMints: () => {
|
|
150
|
+
const { pendingMints } = get();
|
|
151
|
+
return Object.values(pendingMints).filter((m) => m.state.status !== 'failed' && m.state.status !== 'cancelled');
|
|
152
|
+
},
|
|
153
|
+
}), {
|
|
154
|
+
name: 'cross-chain-mint-storage',
|
|
155
|
+
partialize: (state) => ({
|
|
156
|
+
recentMints: state.recentMints,
|
|
157
|
+
}),
|
|
158
|
+
}), { name: 'CrossChainStore' }));
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-chain bridge module for XVM ↔ C-Chain atomic swaps
|
|
3
|
+
*
|
|
4
|
+
* Enables one-click minting of wrapped tokens on C-Chain from X-Chain assets
|
|
5
|
+
* using Warp cross-chain messaging and HTLC atomic swaps.
|
|
6
|
+
*
|
|
7
|
+
* Includes Z-Chain privacy layer for fully shielded cross-chain teleportation:
|
|
8
|
+
* XVM UTXO → ZNote (shielded) → Z-Chain AMM (private swap) → destination
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* // Standard cross-chain mint
|
|
13
|
+
* import { useCrossChainMint } from '@luxfi/exchange/bridge'
|
|
14
|
+
*
|
|
15
|
+
* function MintButton() {
|
|
16
|
+
* const { mint, isLoading } = useCrossChainMint()
|
|
17
|
+
*
|
|
18
|
+
* const handleMint = async () => {
|
|
19
|
+
* const swapId = await mint({
|
|
20
|
+
* sourceAsset: '0x...', // XVM asset ID
|
|
21
|
+
* amount: 1000000n, // 1 token (6 decimals)
|
|
22
|
+
* recipient: '0x...', // C-Chain recipient
|
|
23
|
+
* targetToken: '0x...', // Optional: swap to this token
|
|
24
|
+
* minReceive: 990000n, // Slippage protection
|
|
25
|
+
* })
|
|
26
|
+
* console.log('Mint initiated:', swapId)
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* return (
|
|
30
|
+
* <button onClick={handleMint} disabled={isLoading}>
|
|
31
|
+
* {isLoading ? 'Minting...' : 'Mint on C-Chain'}
|
|
32
|
+
* </button>
|
|
33
|
+
* )
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Private teleport with Z-Chain
|
|
40
|
+
* import { usePrivateTeleport } from '@luxfi/exchange/bridge'
|
|
41
|
+
*
|
|
42
|
+
* function PrivateTeleportButton() {
|
|
43
|
+
* const { teleport, executeSwap, exportToDestination, isLoading } = usePrivateTeleport()
|
|
44
|
+
*
|
|
45
|
+
* const handlePrivateTeleport = async () => {
|
|
46
|
+
* // 1. Initiate shielded teleport (creates ZNote)
|
|
47
|
+
* const teleportId = await teleport({
|
|
48
|
+
* sourceChain: '0x...', // X-Chain ID
|
|
49
|
+
* destChain: '0x...', // C-Chain ID
|
|
50
|
+
* sourceAsset: '0x...', // Asset to teleport
|
|
51
|
+
* destAsset: '0x...', // Asset to receive (if swapping)
|
|
52
|
+
* amount: 1000000n, // Amount (will be encrypted)
|
|
53
|
+
* recipient: '0x...', // Destination address
|
|
54
|
+
* deadline: Math.floor(Date.now() / 1000) + 3600,
|
|
55
|
+
* privateSwap: true, // Use Z-Chain AMM for private swap
|
|
56
|
+
* })
|
|
57
|
+
*
|
|
58
|
+
* // 2. Execute private swap on Z-Chain (optional)
|
|
59
|
+
* await executeSwap(teleportId, '0x...poolId', 990000n)
|
|
60
|
+
*
|
|
61
|
+
* // 3. Export to destination chain with range proof
|
|
62
|
+
* await exportToDestination(teleportId)
|
|
63
|
+
* }
|
|
64
|
+
*
|
|
65
|
+
* return (
|
|
66
|
+
* <button onClick={handlePrivateTeleport} disabled={isLoading}>
|
|
67
|
+
* Private Teleport
|
|
68
|
+
* </button>
|
|
69
|
+
* )
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export * from './types';
|
|
74
|
+
export * from './cross-chain-store';
|
|
75
|
+
export * from './use-cross-chain-mint';
|
|
76
|
+
export * from './private-teleport-types';
|
|
77
|
+
export * from './use-private-teleport';
|
|
78
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AAGH,cAAc,SAAS,CAAA;AACvB,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AAGtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-chain bridge module for XVM ↔ C-Chain atomic swaps
|
|
3
|
+
*
|
|
4
|
+
* Enables one-click minting of wrapped tokens on C-Chain from X-Chain assets
|
|
5
|
+
* using Warp cross-chain messaging and HTLC atomic swaps.
|
|
6
|
+
*
|
|
7
|
+
* Includes Z-Chain privacy layer for fully shielded cross-chain teleportation:
|
|
8
|
+
* XVM UTXO → ZNote (shielded) → Z-Chain AMM (private swap) → destination
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* // Standard cross-chain mint
|
|
13
|
+
* import { useCrossChainMint } from '@luxfi/exchange/bridge'
|
|
14
|
+
*
|
|
15
|
+
* function MintButton() {
|
|
16
|
+
* const { mint, isLoading } = useCrossChainMint()
|
|
17
|
+
*
|
|
18
|
+
* const handleMint = async () => {
|
|
19
|
+
* const swapId = await mint({
|
|
20
|
+
* sourceAsset: '0x...', // XVM asset ID
|
|
21
|
+
* amount: 1000000n, // 1 token (6 decimals)
|
|
22
|
+
* recipient: '0x...', // C-Chain recipient
|
|
23
|
+
* targetToken: '0x...', // Optional: swap to this token
|
|
24
|
+
* minReceive: 990000n, // Slippage protection
|
|
25
|
+
* })
|
|
26
|
+
* console.log('Mint initiated:', swapId)
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* return (
|
|
30
|
+
* <button onClick={handleMint} disabled={isLoading}>
|
|
31
|
+
* {isLoading ? 'Minting...' : 'Mint on C-Chain'}
|
|
32
|
+
* </button>
|
|
33
|
+
* )
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Private teleport with Z-Chain
|
|
40
|
+
* import { usePrivateTeleport } from '@luxfi/exchange/bridge'
|
|
41
|
+
*
|
|
42
|
+
* function PrivateTeleportButton() {
|
|
43
|
+
* const { teleport, executeSwap, exportToDestination, isLoading } = usePrivateTeleport()
|
|
44
|
+
*
|
|
45
|
+
* const handlePrivateTeleport = async () => {
|
|
46
|
+
* // 1. Initiate shielded teleport (creates ZNote)
|
|
47
|
+
* const teleportId = await teleport({
|
|
48
|
+
* sourceChain: '0x...', // X-Chain ID
|
|
49
|
+
* destChain: '0x...', // C-Chain ID
|
|
50
|
+
* sourceAsset: '0x...', // Asset to teleport
|
|
51
|
+
* destAsset: '0x...', // Asset to receive (if swapping)
|
|
52
|
+
* amount: 1000000n, // Amount (will be encrypted)
|
|
53
|
+
* recipient: '0x...', // Destination address
|
|
54
|
+
* deadline: Math.floor(Date.now() / 1000) + 3600,
|
|
55
|
+
* privateSwap: true, // Use Z-Chain AMM for private swap
|
|
56
|
+
* })
|
|
57
|
+
*
|
|
58
|
+
* // 2. Execute private swap on Z-Chain (optional)
|
|
59
|
+
* await executeSwap(teleportId, '0x...poolId', 990000n)
|
|
60
|
+
*
|
|
61
|
+
* // 3. Export to destination chain with range proof
|
|
62
|
+
* await exportToDestination(teleportId)
|
|
63
|
+
* }
|
|
64
|
+
*
|
|
65
|
+
* return (
|
|
66
|
+
* <button onClick={handlePrivateTeleport} disabled={isLoading}>
|
|
67
|
+
* Private Teleport
|
|
68
|
+
* </button>
|
|
69
|
+
* )
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
// Standard cross-chain (public)
|
|
74
|
+
export * from './types';
|
|
75
|
+
export * from './cross-chain-store';
|
|
76
|
+
export * from './use-cross-chain-mint';
|
|
77
|
+
// Private teleport (Z-Chain privacy layer)
|
|
78
|
+
export * from './private-teleport-types';
|
|
79
|
+
export * from './use-private-teleport';
|