@yellow-org/sdk 1.0.1-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.
Files changed (72) hide show
  1. package/README.md +999 -0
  2. package/dist/abis/generated.d.ts +4300 -0
  3. package/dist/abis/generated.js +1 -0
  4. package/dist/app/index.d.ts +2 -0
  5. package/dist/app/index.js +2 -0
  6. package/dist/app/packing.d.ts +7 -0
  7. package/dist/app/packing.js +111 -0
  8. package/dist/app/types.d.ts +91 -0
  9. package/dist/app/types.js +42 -0
  10. package/dist/asset_store.d.ts +13 -0
  11. package/dist/asset_store.js +121 -0
  12. package/dist/blockchain/evm/channel_hub_abi.d.ts +4284 -0
  13. package/dist/blockchain/evm/channel_hub_abi.js +5475 -0
  14. package/dist/blockchain/evm/client.d.ts +46 -0
  15. package/dist/blockchain/evm/client.js +428 -0
  16. package/dist/blockchain/evm/erc20.d.ts +13 -0
  17. package/dist/blockchain/evm/erc20.js +54 -0
  18. package/dist/blockchain/evm/erc20_abi.d.ts +144 -0
  19. package/dist/blockchain/evm/erc20_abi.js +96 -0
  20. package/dist/blockchain/evm/index.d.ts +6 -0
  21. package/dist/blockchain/evm/index.js +6 -0
  22. package/dist/blockchain/evm/interface.d.ts +10 -0
  23. package/dist/blockchain/evm/interface.js +1 -0
  24. package/dist/blockchain/evm/types.d.ts +27 -0
  25. package/dist/blockchain/evm/types.js +1 -0
  26. package/dist/blockchain/evm/utils.d.ts +9 -0
  27. package/dist/blockchain/evm/utils.js +129 -0
  28. package/dist/blockchain/index.d.ts +1 -0
  29. package/dist/blockchain/index.js +1 -0
  30. package/dist/client.d.ts +99 -0
  31. package/dist/client.js +720 -0
  32. package/dist/config.d.ts +12 -0
  33. package/dist/config.js +28 -0
  34. package/dist/core/event.d.ts +29 -0
  35. package/dist/core/event.js +1 -0
  36. package/dist/core/index.d.ts +6 -0
  37. package/dist/core/index.js +6 -0
  38. package/dist/core/interface.d.ts +53 -0
  39. package/dist/core/interface.js +1 -0
  40. package/dist/core/state.d.ts +21 -0
  41. package/dist/core/state.js +267 -0
  42. package/dist/core/state_packer.d.ts +13 -0
  43. package/dist/core/state_packer.js +98 -0
  44. package/dist/core/types.d.ts +203 -0
  45. package/dist/core/types.js +220 -0
  46. package/dist/core/utils.d.ts +16 -0
  47. package/dist/core/utils.js +181 -0
  48. package/dist/index.d.ts +9 -0
  49. package/dist/index.js +9 -0
  50. package/dist/rpc/api.d.ts +181 -0
  51. package/dist/rpc/api.js +1 -0
  52. package/dist/rpc/client.d.ts +36 -0
  53. package/dist/rpc/client.js +102 -0
  54. package/dist/rpc/dialer.d.ts +30 -0
  55. package/dist/rpc/dialer.js +146 -0
  56. package/dist/rpc/error.d.ts +18 -0
  57. package/dist/rpc/error.js +27 -0
  58. package/dist/rpc/index.d.ts +7 -0
  59. package/dist/rpc/index.js +7 -0
  60. package/dist/rpc/message.d.ts +25 -0
  61. package/dist/rpc/message.js +102 -0
  62. package/dist/rpc/methods.d.ts +30 -0
  63. package/dist/rpc/methods.js +27 -0
  64. package/dist/rpc/types.d.ts +101 -0
  65. package/dist/rpc/types.js +1 -0
  66. package/dist/signers.d.ts +48 -0
  67. package/dist/signers.js +96 -0
  68. package/dist/utils/sign.d.ts +2 -0
  69. package/dist/utils/sign.js +8 -0
  70. package/dist/utils.d.ts +42 -0
  71. package/dist/utils.js +226 -0
  72. package/package.json +89 -0
@@ -0,0 +1,12 @@
1
+ export interface Config {
2
+ url: string;
3
+ handshakeTimeout?: number;
4
+ errorHandler?: (error: Error) => void;
5
+ blockchainRPCs?: Map<bigint, string>;
6
+ pingInterval?: number;
7
+ }
8
+ export type Option = (config: Config) => void;
9
+ export declare const DefaultConfig: Partial<Config>;
10
+ export declare function withHandshakeTimeout(timeout: number): Option;
11
+ export declare function withErrorHandler(handler: (error: Error) => void): Option;
12
+ export declare function withBlockchainRPC(chainId: bigint, rpcUrl: string): Option;
package/dist/config.js ADDED
@@ -0,0 +1,28 @@
1
+ function defaultErrorHandler(err) {
2
+ if (err) {
3
+ console.error('[nitrolite]', 'connection error:', err);
4
+ }
5
+ }
6
+ export const DefaultConfig = {
7
+ handshakeTimeout: 5000,
8
+ errorHandler: defaultErrorHandler,
9
+ blockchainRPCs: new Map(),
10
+ };
11
+ export function withHandshakeTimeout(timeout) {
12
+ return (config) => {
13
+ config.handshakeTimeout = timeout;
14
+ };
15
+ }
16
+ export function withErrorHandler(handler) {
17
+ return (config) => {
18
+ config.errorHandler = handler;
19
+ };
20
+ }
21
+ export function withBlockchainRPC(chainId, rpcUrl) {
22
+ return (config) => {
23
+ if (!config.blockchainRPCs) {
24
+ config.blockchainRPCs = new Map();
25
+ }
26
+ config.blockchainRPCs.set(chainId, rpcUrl);
27
+ };
28
+ }
@@ -0,0 +1,29 @@
1
+ import { Address, Hex } from 'viem';
2
+ export interface ChannelEvent {
3
+ channelId: string;
4
+ stateVersion: bigint;
5
+ }
6
+ export interface ChannelChallengedEvent {
7
+ channelId: string;
8
+ stateVersion: bigint;
9
+ challengeExpiry: bigint;
10
+ }
11
+ export interface BlockchainEvent {
12
+ contractAddress: Address;
13
+ blockchainId: bigint;
14
+ name: string;
15
+ blockNumber: bigint;
16
+ transactionHash: Hex;
17
+ logIndex: number;
18
+ }
19
+ export type HomeChannelCreatedEvent = ChannelEvent;
20
+ export type HomeChannelMigratedEvent = ChannelEvent;
21
+ export type HomeChannelCheckpointedEvent = ChannelEvent;
22
+ export type HomeChannelChallengedEvent = ChannelChallengedEvent;
23
+ export type HomeChannelClosedEvent = ChannelEvent;
24
+ export type EscrowDepositInitiatedEvent = ChannelEvent;
25
+ export type EscrowDepositChallengedEvent = ChannelChallengedEvent;
26
+ export type EscrowDepositFinalizedEvent = ChannelEvent;
27
+ export type EscrowWithdrawalInitiatedEvent = ChannelEvent;
28
+ export type EscrowWithdrawalChallengedEvent = ChannelChallengedEvent;
29
+ export type EscrowWithdrawalFinalizedEvent = ChannelEvent;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ export * from './types';
2
+ export * from './interface';
3
+ export * from './event';
4
+ export * from './utils';
5
+ export * from './state';
6
+ export * from './state_packer';
@@ -0,0 +1,6 @@
1
+ export * from './types';
2
+ export * from './interface';
3
+ export * from './event';
4
+ export * from './utils';
5
+ export * from './state';
6
+ export * from './state_packer';
@@ -0,0 +1,53 @@
1
+ import { Address, Hex } from 'viem';
2
+ import Decimal from 'decimal.js';
3
+ import { State, ChannelDefinition, HomeChannelDataResponse, EscrowDepositDataResponse, EscrowWithdrawalDataResponse } from './types';
4
+ import { HomeChannelCreatedEvent, HomeChannelMigratedEvent, HomeChannelCheckpointedEvent, HomeChannelChallengedEvent, HomeChannelClosedEvent, EscrowDepositInitiatedEvent, EscrowDepositChallengedEvent, EscrowDepositFinalizedEvent, EscrowWithdrawalInitiatedEvent, EscrowWithdrawalChallengedEvent, EscrowWithdrawalFinalizedEvent } from './event';
5
+ export interface Listener {
6
+ listen(): Promise<void>;
7
+ }
8
+ export interface Client {
9
+ getAccountsBalances(accounts: Address[], tokens: Address[]): Promise<Decimal[][]>;
10
+ getTokenBalance(asset: string, walletAddress: Address): Promise<Decimal>;
11
+ approve(asset: string, amount: Decimal): Promise<Hex>;
12
+ getNodeBalance(token: Address): Promise<Decimal>;
13
+ getOpenChannels(user: Address): Promise<string[]>;
14
+ getHomeChannelData(homeChannelId: string): Promise<HomeChannelDataResponse>;
15
+ getEscrowDepositData(escrowChannelId: string): Promise<EscrowDepositDataResponse>;
16
+ getEscrowWithdrawalData(escrowChannelId: string): Promise<EscrowWithdrawalDataResponse>;
17
+ deposit(node: Address, token: Address, amount: Decimal): Promise<Hex>;
18
+ withdraw(node: Address, token: Address, amount: Decimal): Promise<Hex>;
19
+ create(def: ChannelDefinition, initCCS: State): Promise<Hex>;
20
+ migrateChannelHere(def: ChannelDefinition, candidate: State): Promise<Hex>;
21
+ checkpoint(candidate: State): Promise<Hex>;
22
+ challenge(candidate: State, challengerSig: Uint8Array, challengerIdx: number): Promise<Hex>;
23
+ close(candidate: State): Promise<Hex>;
24
+ initiateEscrowDeposit(def: ChannelDefinition, initCCS: State): Promise<Hex>;
25
+ challengeEscrowDeposit(candidate: State, challengerSig: Uint8Array, challengerIdx: number): Promise<Hex>;
26
+ finalizeEscrowDeposit(candidate: State): Promise<Hex>;
27
+ initiateEscrowWithdrawal(def: ChannelDefinition, initCCS: State): Promise<Hex>;
28
+ challengeEscrowWithdrawal(candidate: State, challengerSig: Uint8Array, challengerIdx: number): Promise<Hex>;
29
+ finalizeEscrowWithdrawal(candidate: State): Promise<Hex>;
30
+ }
31
+ export interface StateAdvancer {
32
+ validateAdvancement(currentState: State, proposedState: State): Promise<void>;
33
+ }
34
+ export interface StatePacker {
35
+ packState(state: State): Promise<`0x${string}`>;
36
+ }
37
+ export interface AssetStore {
38
+ getAssetDecimals(asset: string): Promise<number>;
39
+ getTokenDecimals(blockchainId: bigint, tokenAddress: Address): Promise<number>;
40
+ }
41
+ export interface BlockchainEventHandler {
42
+ handleHomeChannelCreated(event: HomeChannelCreatedEvent): Promise<void>;
43
+ handleHomeChannelMigrated(event: HomeChannelMigratedEvent): Promise<void>;
44
+ handleHomeChannelCheckpointed(event: HomeChannelCheckpointedEvent): Promise<void>;
45
+ handleHomeChannelChallenged(event: HomeChannelChallengedEvent): Promise<void>;
46
+ handleHomeChannelClosed(event: HomeChannelClosedEvent): Promise<void>;
47
+ handleEscrowDepositInitiated(event: EscrowDepositInitiatedEvent): Promise<void>;
48
+ handleEscrowDepositChallenged(event: EscrowDepositChallengedEvent): Promise<void>;
49
+ handleEscrowDepositFinalized(event: EscrowDepositFinalizedEvent): Promise<void>;
50
+ handleEscrowWithdrawalInitiated(event: EscrowWithdrawalInitiatedEvent): Promise<void>;
51
+ handleEscrowWithdrawalChallenged(event: EscrowWithdrawalChallengedEvent): Promise<void>;
52
+ handleEscrowWithdrawalFinalized(event: EscrowWithdrawalFinalizedEvent): Promise<void>;
53
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import { Address } from 'viem';
2
+ import Decimal from 'decimal.js';
3
+ import { State, Transition, ChannelDefinition } from './types';
4
+ export declare function getLastTransition(state: State): Transition | null;
5
+ export declare function isFinal(state: State): boolean;
6
+ export declare function nextState(state: State): State;
7
+ export declare function applyChannelCreation(state: State, channelDef: ChannelDefinition, blockchainId: bigint, tokenAddress: Address, nodeAddress: Address): string;
8
+ export declare function applyReceiverTransitions(state: State, ...transitions: Transition[]): void;
9
+ export declare function applyAcknowledgementTransition(state: State): Transition;
10
+ export declare function applyHomeDepositTransition(state: State, amount: Decimal): Transition;
11
+ export declare function applyHomeWithdrawalTransition(state: State, amount: Decimal): Transition;
12
+ export declare function applyTransferSendTransition(state: State, recipient: string, amount: Decimal): Transition;
13
+ export declare function applyTransferReceiveTransition(state: State, sender: string, amount: Decimal, txId: string): Transition;
14
+ export declare function applyCommitTransition(state: State, accountId: string, amount: Decimal): Transition;
15
+ export declare function applyReleaseTransition(state: State, accountId: string, amount: Decimal): Transition;
16
+ export declare function applyMutualLockTransition(state: State, blockchainId: bigint, tokenAddress: Address, amount: Decimal): Transition;
17
+ export declare function applyEscrowDepositTransition(state: State, amount: Decimal): Transition;
18
+ export declare function applyEscrowLockTransition(state: State, blockchainId: bigint, tokenAddress: Address, amount: Decimal): Transition;
19
+ export declare function applyEscrowWithdrawTransition(state: State, amount: Decimal): Transition;
20
+ export declare function applyMigrateTransition(state: State, amount: Decimal): Transition;
21
+ export declare function applyFinalizeTransition(state: State): Transition;
@@ -0,0 +1,267 @@
1
+ import Decimal from 'decimal.js';
2
+ import { TransitionType, newTransition, } from './types';
3
+ import { getHomeChannelId, getEscrowChannelId, getStateId, getSenderTransactionId, getReceiverTransactionId } from './utils';
4
+ export function getLastTransition(state) {
5
+ if (state.transition.type === TransitionType.Void) {
6
+ return null;
7
+ }
8
+ if (state.transition.type === TransitionType.TransferReceive ||
9
+ state.transition.type === TransitionType.Release) {
10
+ return null;
11
+ }
12
+ return state.transition;
13
+ }
14
+ export function isFinal(state) {
15
+ return state.transition.type === TransitionType.Finalize;
16
+ }
17
+ export function nextState(state) {
18
+ let newState;
19
+ const voidTransition = { type: TransitionType.Void, txId: '', amount: new Decimal(0) };
20
+ if (isFinal(state)) {
21
+ newState = {
22
+ id: '',
23
+ transition: voidTransition,
24
+ asset: state.asset,
25
+ userWallet: state.userWallet,
26
+ epoch: state.epoch + 1n,
27
+ version: 0n,
28
+ homeChannelId: undefined,
29
+ escrowChannelId: undefined,
30
+ homeLedger: {
31
+ tokenAddress: '0x0',
32
+ blockchainId: 0n,
33
+ userBalance: new Decimal(0),
34
+ userNetFlow: new Decimal(0),
35
+ nodeBalance: new Decimal(0),
36
+ nodeNetFlow: new Decimal(0),
37
+ },
38
+ escrowLedger: undefined,
39
+ };
40
+ }
41
+ else {
42
+ newState = {
43
+ id: '',
44
+ transition: voidTransition,
45
+ asset: state.asset,
46
+ userWallet: state.userWallet,
47
+ epoch: state.epoch,
48
+ version: state.version + 1n,
49
+ homeChannelId: state.homeChannelId,
50
+ escrowChannelId: state.escrowChannelId,
51
+ homeLedger: { ...state.homeLedger },
52
+ escrowLedger: undefined,
53
+ };
54
+ }
55
+ if (state.escrowLedger) {
56
+ newState.escrowLedger = { ...state.escrowLedger };
57
+ if (!state.userSig) {
58
+ newState.transition = { ...state.transition };
59
+ }
60
+ else {
61
+ if (state.transition.type === TransitionType.EscrowDeposit ||
62
+ state.transition.type === TransitionType.EscrowWithdraw) {
63
+ newState.escrowChannelId = undefined;
64
+ newState.escrowLedger = undefined;
65
+ }
66
+ }
67
+ }
68
+ newState.id = getStateId(newState.userWallet, newState.asset, newState.epoch, newState.version);
69
+ return newState;
70
+ }
71
+ export function applyChannelCreation(state, channelDef, blockchainId, tokenAddress, nodeAddress) {
72
+ state.homeLedger.tokenAddress = tokenAddress;
73
+ state.homeLedger.blockchainId = blockchainId;
74
+ const homeChannelId = getHomeChannelId(nodeAddress, state.userWallet, state.asset, channelDef.nonce, channelDef.challenge, channelDef.approvedSigValidators);
75
+ state.homeChannelId = homeChannelId;
76
+ return homeChannelId;
77
+ }
78
+ export function applyReceiverTransitions(state, ...transitions) {
79
+ for (const transition of transitions) {
80
+ switch (transition.type) {
81
+ case TransitionType.TransferReceive:
82
+ if (!transition.accountId) {
83
+ throw new Error('missing account ID for transfer receive transition');
84
+ }
85
+ applyTransferReceiveTransition(state, transition.accountId, transition.amount, transition.txId);
86
+ break;
87
+ case TransitionType.Release:
88
+ if (!transition.accountId) {
89
+ throw new Error('missing account ID for release transition');
90
+ }
91
+ applyReleaseTransition(state, transition.accountId, transition.amount);
92
+ break;
93
+ default:
94
+ throw new Error(`transition '${transition.type}' cannot be applied by receiver`);
95
+ }
96
+ }
97
+ }
98
+ export function applyAcknowledgementTransition(state) {
99
+ if (state.transition.type !== TransitionType.Void) {
100
+ throw new Error(`state already has a transition: ${state.transition.type}`);
101
+ }
102
+ const zeroHash = '0x0000000000000000000000000000000000000000000000000000000000000000';
103
+ const newTransitionObj = newTransition(TransitionType.Acknowledgement, zeroHash, zeroHash, new Decimal(0));
104
+ state.transition = newTransitionObj;
105
+ return newTransitionObj;
106
+ }
107
+ export function applyHomeDepositTransition(state, amount) {
108
+ if (!state.homeChannelId) {
109
+ throw new Error('missing home channel ID');
110
+ }
111
+ const accountId = state.homeChannelId;
112
+ const txId = getSenderTransactionId(accountId, state.id);
113
+ const newTransitionObj = newTransition(TransitionType.HomeDeposit, txId, accountId, amount);
114
+ state.transition = newTransitionObj;
115
+ state.homeLedger.userNetFlow = state.homeLedger.userNetFlow.add(newTransitionObj.amount);
116
+ state.homeLedger.userBalance = state.homeLedger.userBalance.add(newTransitionObj.amount);
117
+ return newTransitionObj;
118
+ }
119
+ export function applyHomeWithdrawalTransition(state, amount) {
120
+ if (!state.homeChannelId) {
121
+ throw new Error('missing home channel ID');
122
+ }
123
+ const accountId = state.homeChannelId;
124
+ const txId = getSenderTransactionId(accountId, state.id);
125
+ const newTransitionObj = newTransition(TransitionType.HomeWithdrawal, txId, accountId, amount);
126
+ state.transition = newTransitionObj;
127
+ state.homeLedger.userNetFlow = state.homeLedger.userNetFlow.sub(newTransitionObj.amount);
128
+ state.homeLedger.userBalance = state.homeLedger.userBalance.sub(newTransitionObj.amount);
129
+ return newTransitionObj;
130
+ }
131
+ export function applyTransferSendTransition(state, recipient, amount) {
132
+ const accountId = recipient;
133
+ const txId = getSenderTransactionId(accountId, state.id);
134
+ const newTransitionObj = newTransition(TransitionType.TransferSend, txId, accountId, amount);
135
+ state.transition = newTransitionObj;
136
+ state.homeLedger.userBalance = state.homeLedger.userBalance.sub(newTransitionObj.amount);
137
+ state.homeLedger.nodeNetFlow = state.homeLedger.nodeNetFlow.sub(newTransitionObj.amount);
138
+ return newTransitionObj;
139
+ }
140
+ export function applyTransferReceiveTransition(state, sender, amount, txId) {
141
+ const accountId = sender;
142
+ const newTransitionObj = newTransition(TransitionType.TransferReceive, txId, accountId, amount);
143
+ state.transition = newTransitionObj;
144
+ state.homeLedger.userBalance = state.homeLedger.userBalance.add(newTransitionObj.amount);
145
+ state.homeLedger.nodeNetFlow = state.homeLedger.nodeNetFlow.add(newTransitionObj.amount);
146
+ return newTransitionObj;
147
+ }
148
+ export function applyCommitTransition(state, accountId, amount) {
149
+ const txId = getSenderTransactionId(accountId, state.id);
150
+ const newTransitionObj = newTransition(TransitionType.Commit, txId, accountId, amount);
151
+ state.transition = newTransitionObj;
152
+ state.homeLedger.userBalance = state.homeLedger.userBalance.sub(newTransitionObj.amount);
153
+ state.homeLedger.nodeNetFlow = state.homeLedger.nodeNetFlow.sub(newTransitionObj.amount);
154
+ return newTransitionObj;
155
+ }
156
+ export function applyReleaseTransition(state, accountId, amount) {
157
+ const txId = getReceiverTransactionId(accountId, state.id);
158
+ const newTransitionObj = newTransition(TransitionType.Release, txId, accountId, amount);
159
+ state.transition = newTransitionObj;
160
+ state.homeLedger.userBalance = state.homeLedger.userBalance.add(newTransitionObj.amount);
161
+ state.homeLedger.nodeNetFlow = state.homeLedger.nodeNetFlow.add(newTransitionObj.amount);
162
+ return newTransitionObj;
163
+ }
164
+ export function applyMutualLockTransition(state, blockchainId, tokenAddress, amount) {
165
+ if (!state.homeChannelId) {
166
+ throw new Error('missing home channel ID');
167
+ }
168
+ if (blockchainId === 0n) {
169
+ throw new Error('invalid blockchain ID');
170
+ }
171
+ if (!tokenAddress || tokenAddress === '0x0') {
172
+ throw new Error('invalid token address');
173
+ }
174
+ const escrowChannelId = getEscrowChannelId(state.homeChannelId, state.version);
175
+ state.escrowChannelId = escrowChannelId;
176
+ const accountId = escrowChannelId;
177
+ const txId = getSenderTransactionId(accountId, state.id);
178
+ const newTransitionObj = newTransition(TransitionType.MutualLock, txId, accountId, amount);
179
+ state.transition = newTransitionObj;
180
+ state.homeLedger.nodeBalance = state.homeLedger.nodeBalance.add(newTransitionObj.amount);
181
+ state.homeLedger.nodeNetFlow = state.homeLedger.nodeNetFlow.add(newTransitionObj.amount);
182
+ state.escrowLedger = {
183
+ blockchainId,
184
+ tokenAddress,
185
+ userBalance: new Decimal(0).add(newTransitionObj.amount),
186
+ userNetFlow: new Decimal(0).add(newTransitionObj.amount),
187
+ nodeBalance: new Decimal(0),
188
+ nodeNetFlow: new Decimal(0),
189
+ };
190
+ return newTransitionObj;
191
+ }
192
+ export function applyEscrowDepositTransition(state, amount) {
193
+ if (!state.escrowChannelId) {
194
+ throw new Error('internal error: escrow channel ID is nil');
195
+ }
196
+ if (!state.escrowLedger) {
197
+ throw new Error('escrow ledger is nil');
198
+ }
199
+ const accountId = state.escrowChannelId;
200
+ const txId = getSenderTransactionId(accountId, state.id);
201
+ const newTransitionObj = newTransition(TransitionType.EscrowDeposit, txId, accountId, amount);
202
+ state.transition = newTransitionObj;
203
+ state.homeLedger.userBalance = state.homeLedger.userBalance.add(newTransitionObj.amount);
204
+ state.homeLedger.nodeNetFlow = state.homeLedger.nodeNetFlow.add(newTransitionObj.amount);
205
+ state.escrowLedger.userBalance = state.escrowLedger.userBalance.sub(newTransitionObj.amount);
206
+ state.escrowLedger.nodeNetFlow = state.escrowLedger.nodeNetFlow.sub(newTransitionObj.amount);
207
+ return newTransitionObj;
208
+ }
209
+ export function applyEscrowLockTransition(state, blockchainId, tokenAddress, amount) {
210
+ if (!state.homeChannelId) {
211
+ throw new Error('missing home channel ID');
212
+ }
213
+ if (blockchainId === 0n) {
214
+ throw new Error('invalid blockchain ID');
215
+ }
216
+ if (!tokenAddress || tokenAddress === '0x0') {
217
+ throw new Error('invalid token address');
218
+ }
219
+ const escrowChannelId = getEscrowChannelId(state.homeChannelId, state.version);
220
+ state.escrowChannelId = escrowChannelId;
221
+ const accountId = escrowChannelId;
222
+ const txId = getSenderTransactionId(accountId, state.id);
223
+ const newTransitionObj = newTransition(TransitionType.EscrowLock, txId, accountId, amount);
224
+ state.transition = newTransitionObj;
225
+ state.escrowLedger = {
226
+ blockchainId,
227
+ tokenAddress,
228
+ userBalance: new Decimal(0),
229
+ userNetFlow: new Decimal(0),
230
+ nodeBalance: new Decimal(0).add(newTransitionObj.amount),
231
+ nodeNetFlow: new Decimal(0).add(newTransitionObj.amount),
232
+ };
233
+ return newTransitionObj;
234
+ }
235
+ export function applyEscrowWithdrawTransition(state, amount) {
236
+ if (!state.escrowChannelId) {
237
+ throw new Error('internal error: escrow channel ID is nil');
238
+ }
239
+ if (!state.escrowLedger) {
240
+ throw new Error('escrow ledger is nil');
241
+ }
242
+ const accountId = state.escrowChannelId;
243
+ const txId = getSenderTransactionId(accountId, state.id);
244
+ const newTransitionObj = newTransition(TransitionType.EscrowWithdraw, txId, accountId, amount);
245
+ state.transition = newTransitionObj;
246
+ state.homeLedger.userBalance = state.homeLedger.userBalance.sub(newTransitionObj.amount);
247
+ state.homeLedger.nodeNetFlow = state.homeLedger.nodeNetFlow.sub(newTransitionObj.amount);
248
+ state.escrowLedger.userNetFlow = state.escrowLedger.userNetFlow.sub(newTransitionObj.amount);
249
+ state.escrowLedger.nodeBalance = state.escrowLedger.nodeBalance.sub(newTransitionObj.amount);
250
+ return newTransitionObj;
251
+ }
252
+ export function applyMigrateTransition(state, amount) {
253
+ throw new Error('migrate transition not implemented yet');
254
+ }
255
+ export function applyFinalizeTransition(state) {
256
+ if (!state.homeChannelId) {
257
+ throw new Error('missing home channel ID');
258
+ }
259
+ const accountId = state.homeChannelId;
260
+ const amount = state.homeLedger.userBalance;
261
+ const txId = getSenderTransactionId(accountId, state.id);
262
+ const newTransitionObj = newTransition(TransitionType.Finalize, txId, accountId, amount);
263
+ state.transition = newTransitionObj;
264
+ state.homeLedger.userNetFlow = state.homeLedger.userNetFlow.sub(state.homeLedger.userBalance);
265
+ state.homeLedger.userBalance = new Decimal(0);
266
+ return newTransitionObj;
267
+ }
@@ -0,0 +1,13 @@
1
+ import { State } from './types';
2
+ import { AssetStore, StatePacker } from './interface';
3
+ export declare class StatePackerV1 implements StatePacker {
4
+ private assetStore;
5
+ constructor(assetStore: AssetStore);
6
+ private packSigningData;
7
+ private packWithChannelId;
8
+ packState(state: State): Promise<`0x${string}`>;
9
+ packChallengeState(state: State): Promise<`0x${string}`>;
10
+ }
11
+ export declare function newStatePackerV1(assetStore: AssetStore): StatePackerV1;
12
+ export declare function packState(state: State, assetStore: AssetStore): Promise<`0x${string}`>;
13
+ export declare function packChallengeState(state: State, assetStore: AssetStore): Promise<`0x${string}`>;
@@ -0,0 +1,98 @@
1
+ import { encodeAbiParameters, concat, toHex } from 'viem';
2
+ import { getStateTransitionHash, transitionToIntent, decimalToBigInt } from './utils';
3
+ export class StatePackerV1 {
4
+ constructor(assetStore) {
5
+ this.assetStore = assetStore;
6
+ }
7
+ async packSigningData(state) {
8
+ if (!state.homeChannelId) {
9
+ throw new Error('state.homeChannelId is required for packing');
10
+ }
11
+ const channelId = state.homeChannelId;
12
+ const metadata = getStateTransitionHash(state.transition);
13
+ const homeDecimals = await this.assetStore.getTokenDecimals(state.homeLedger.blockchainId, state.homeLedger.tokenAddress);
14
+ const homeLedger = {
15
+ chainId: state.homeLedger.blockchainId,
16
+ token: state.homeLedger.tokenAddress,
17
+ decimals: homeDecimals,
18
+ userAllocation: decimalToBigInt(state.homeLedger.userBalance, homeDecimals),
19
+ userNetFlow: decimalToBigInt(state.homeLedger.userNetFlow, homeDecimals),
20
+ nodeAllocation: decimalToBigInt(state.homeLedger.nodeBalance, homeDecimals),
21
+ nodeNetFlow: decimalToBigInt(state.homeLedger.nodeNetFlow, homeDecimals),
22
+ };
23
+ let nonHomeLedger;
24
+ if (state.escrowLedger) {
25
+ const escrowDecimals = await this.assetStore.getTokenDecimals(state.escrowLedger.blockchainId, state.escrowLedger.tokenAddress);
26
+ nonHomeLedger = {
27
+ chainId: state.escrowLedger.blockchainId,
28
+ token: state.escrowLedger.tokenAddress,
29
+ decimals: escrowDecimals,
30
+ userAllocation: decimalToBigInt(state.escrowLedger.userBalance, escrowDecimals),
31
+ userNetFlow: decimalToBigInt(state.escrowLedger.userNetFlow, escrowDecimals),
32
+ nodeAllocation: decimalToBigInt(state.escrowLedger.nodeBalance, escrowDecimals),
33
+ nodeNetFlow: decimalToBigInt(state.escrowLedger.nodeNetFlow, escrowDecimals),
34
+ };
35
+ }
36
+ else {
37
+ nonHomeLedger = {
38
+ chainId: 0n,
39
+ token: '0x0000000000000000000000000000000000000000',
40
+ decimals: 0,
41
+ userAllocation: 0n,
42
+ userNetFlow: 0n,
43
+ nodeAllocation: 0n,
44
+ nodeNetFlow: 0n,
45
+ };
46
+ }
47
+ const intent = transitionToIntent(state.transition);
48
+ const ledgerComponents = [
49
+ { name: 'chainId', type: 'uint64' },
50
+ { name: 'token', type: 'address' },
51
+ { name: 'decimals', type: 'uint8' },
52
+ { name: 'userAllocation', type: 'uint256' },
53
+ { name: 'userNetFlow', type: 'int256' },
54
+ { name: 'nodeAllocation', type: 'uint256' },
55
+ { name: 'nodeNetFlow', type: 'int256' },
56
+ ];
57
+ const signingData = encodeAbiParameters([
58
+ { type: 'uint64' },
59
+ { type: 'uint8' },
60
+ { type: 'bytes32' },
61
+ { type: 'tuple', components: ledgerComponents },
62
+ { type: 'tuple', components: ledgerComponents },
63
+ ], [
64
+ state.version,
65
+ intent,
66
+ metadata,
67
+ homeLedger,
68
+ nonHomeLedger,
69
+ ]);
70
+ return { channelId, signingData };
71
+ }
72
+ packWithChannelId(channelId, signingData) {
73
+ return encodeAbiParameters([
74
+ { type: 'bytes32' },
75
+ { type: 'bytes' },
76
+ ], [channelId, signingData]);
77
+ }
78
+ async packState(state) {
79
+ const { channelId, signingData } = await this.packSigningData(state);
80
+ return this.packWithChannelId(channelId, signingData);
81
+ }
82
+ async packChallengeState(state) {
83
+ const { channelId, signingData } = await this.packSigningData(state);
84
+ const challengeSigningData = concat([signingData, toHex('challenge')]);
85
+ return this.packWithChannelId(channelId, challengeSigningData);
86
+ }
87
+ }
88
+ export function newStatePackerV1(assetStore) {
89
+ return new StatePackerV1(assetStore);
90
+ }
91
+ export async function packState(state, assetStore) {
92
+ const packer = newStatePackerV1(assetStore);
93
+ return packer.packState(state);
94
+ }
95
+ export async function packChallengeState(state, assetStore) {
96
+ const packer = newStatePackerV1(assetStore);
97
+ return packer.packChallengeState(state);
98
+ }