@unionlabs/payments 0.2.1 → 0.3.1
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/ChainRegistry/package.json +6 -0
- package/README.md +283 -1
- package/dist/cjs/Attestor.js +9 -2
- package/dist/cjs/Attestor.js.map +1 -1
- package/dist/cjs/ChainRegistry.js +24 -0
- package/dist/cjs/ChainRegistry.js.map +1 -0
- package/dist/cjs/Domain.js +8 -2
- package/dist/cjs/Domain.js.map +1 -1
- package/dist/cjs/Error.js +1 -1
- package/dist/cjs/Error.js.map +1 -1
- package/dist/cjs/EvmPublicClient.js +5 -277
- package/dist/cjs/EvmPublicClient.js.map +1 -1
- package/dist/cjs/EvmWalletClient.js +7 -642
- package/dist/cjs/EvmWalletClient.js.map +1 -1
- package/dist/cjs/Payment.js +86 -79
- package/dist/cjs/Payment.js.map +1 -1
- package/dist/cjs/Prover.js +2 -2
- package/dist/cjs/Prover.js.map +1 -1
- package/dist/cjs/PublicClient.js +2 -2
- package/dist/cjs/PublicClient.js.map +1 -1
- package/dist/cjs/WalletClient.js +2 -2
- package/dist/cjs/WalletClient.js.map +1 -1
- package/dist/cjs/constants/ibc-core-registry.js +7 -9
- package/dist/cjs/constants/ibc-core-registry.js.map +1 -1
- package/dist/cjs/constants/z-asset-registry.js +9 -7
- package/dist/cjs/constants/z-asset-registry.js.map +1 -1
- package/dist/cjs/internal/evmPublicClient.js +261 -0
- package/dist/cjs/internal/evmPublicClient.js.map +1 -0
- package/dist/cjs/internal/evmWalletClient.js +650 -0
- package/dist/cjs/internal/evmWalletClient.js.map +1 -1
- package/dist/cjs/internal/publicClient.js +0 -2
- package/dist/cjs/internal/publicClient.js.map +1 -1
- package/dist/cjs/promises/Payment.js +4 -3
- package/dist/cjs/promises/Payment.js.map +1 -1
- package/dist/cjs/promises/PublicClient.js +1 -2
- package/dist/cjs/promises/PublicClient.js.map +1 -1
- package/dist/cjs/promises/WalletClient.js +0 -1
- package/dist/cjs/promises/WalletClient.js.map +1 -1
- package/dist/cjs/rpc.js +3 -5
- package/dist/cjs/rpc.js.map +1 -1
- package/dist/dts/Attestor.d.ts +21 -6
- package/dist/dts/Attestor.d.ts.map +1 -1
- package/dist/dts/ChainRegistry.d.ts +6 -0
- package/dist/dts/ChainRegistry.d.ts.map +1 -0
- package/dist/dts/Domain.d.ts +92 -59
- package/dist/dts/Domain.d.ts.map +1 -1
- package/dist/dts/Error.d.ts +2 -2
- package/dist/dts/Error.d.ts.map +1 -1
- package/dist/dts/EvmPublicClient.d.ts +7 -19
- package/dist/dts/EvmPublicClient.d.ts.map +1 -1
- package/dist/dts/EvmWalletClient.d.ts +7 -23
- package/dist/dts/EvmWalletClient.d.ts.map +1 -1
- package/dist/dts/Payment.d.ts +72 -71
- package/dist/dts/Payment.d.ts.map +1 -1
- package/dist/dts/Prover.d.ts +6 -0
- package/dist/dts/Prover.d.ts.map +1 -1
- package/dist/dts/PublicClient.d.ts +11 -15
- package/dist/dts/PublicClient.d.ts.map +1 -1
- package/dist/dts/WalletClient.d.ts +10 -6
- package/dist/dts/WalletClient.d.ts.map +1 -1
- package/dist/dts/constants/ibc-core-registry.d.ts +5 -6
- package/dist/dts/constants/ibc-core-registry.d.ts.map +1 -1
- package/dist/dts/constants/z-asset-registry.d.ts +4 -4
- package/dist/dts/constants/z-asset-registry.d.ts.map +1 -1
- package/dist/dts/internal/evm.d.ts +3 -3
- package/dist/dts/internal/evm.d.ts.map +1 -1
- package/dist/dts/internal/evmPublicClient.d.ts +6 -0
- package/dist/dts/internal/evmPublicClient.d.ts.map +1 -0
- package/dist/dts/promises/Attestor.d.ts +5 -5
- package/dist/dts/promises/EvmPublicClient.d.ts +73 -74
- package/dist/dts/promises/EvmPublicClient.d.ts.map +1 -1
- package/dist/dts/promises/EvmWalletClient.d.ts +4 -5
- package/dist/dts/promises/EvmWalletClient.d.ts.map +1 -1
- package/dist/dts/promises/Payment.d.ts +39 -17
- package/dist/dts/promises/Payment.d.ts.map +1 -1
- package/dist/dts/promises/PublicClient.d.ts +3 -4
- package/dist/dts/promises/PublicClient.d.ts.map +1 -1
- package/dist/dts/promises/WalletClient.d.ts +77 -34
- package/dist/dts/promises/WalletClient.d.ts.map +1 -1
- package/dist/dts/rpc.d.ts +31 -0
- package/dist/dts/rpc.d.ts.map +1 -1
- package/dist/esm/Attestor.js +8 -1
- package/dist/esm/Attestor.js.map +1 -1
- package/dist/esm/ChainRegistry.js +16 -0
- package/dist/esm/ChainRegistry.js.map +1 -0
- package/dist/esm/Domain.js +7 -1
- package/dist/esm/Domain.js.map +1 -1
- package/dist/esm/Error.js +1 -1
- package/dist/esm/Error.js.map +1 -1
- package/dist/esm/EvmPublicClient.js +4 -275
- package/dist/esm/EvmPublicClient.js.map +1 -1
- package/dist/esm/EvmWalletClient.js +5 -638
- package/dist/esm/EvmWalletClient.js.map +1 -1
- package/dist/esm/Payment.js +84 -78
- package/dist/esm/Payment.js.map +1 -1
- package/dist/esm/Prover.js +1 -1
- package/dist/esm/Prover.js.map +1 -1
- package/dist/esm/PublicClient.js +2 -2
- package/dist/esm/PublicClient.js.map +1 -1
- package/dist/esm/WalletClient.js +2 -2
- package/dist/esm/WalletClient.js.map +1 -1
- package/dist/esm/constants/ibc-core-registry.js +5 -6
- package/dist/esm/constants/ibc-core-registry.js.map +1 -1
- package/dist/esm/constants/z-asset-registry.js +7 -4
- package/dist/esm/constants/z-asset-registry.js.map +1 -1
- package/dist/esm/internal/evmPublicClient.js +253 -0
- package/dist/esm/internal/evmPublicClient.js.map +1 -0
- package/dist/esm/internal/evmWalletClient.js +647 -1
- package/dist/esm/internal/evmWalletClient.js.map +1 -1
- package/dist/esm/internal/publicClient.js +0 -2
- package/dist/esm/internal/publicClient.js.map +1 -1
- package/dist/esm/promises/Payment.js +2 -2
- package/dist/esm/promises/Payment.js.map +1 -1
- package/dist/esm/promises/PublicClient.js +2 -3
- package/dist/esm/promises/PublicClient.js.map +1 -1
- package/dist/esm/promises/WalletClient.js +0 -1
- package/dist/esm/promises/WalletClient.js.map +1 -1
- package/dist/esm/rpc.js +2 -4
- package/dist/esm/rpc.js.map +1 -1
- package/package.json +15 -3
- package/src/Attestor.ts +12 -3
- package/src/ChainRegistry.ts +27 -0
- package/src/Domain.ts +30 -9
- package/src/Error.ts +1 -0
- package/src/EvmPublicClient.ts +9 -488
- package/src/EvmWalletClient.ts +21 -973
- package/src/Payment.ts +234 -159
- package/src/Prover.ts +2 -2
- package/src/PublicClient.ts +11 -18
- package/src/WalletClient.ts +11 -7
- package/src/constants/ibc-core-registry.ts +14 -14
- package/src/constants/z-asset-registry.ts +10 -7
- package/src/internal/evmPublicClient.ts +459 -0
- package/src/internal/evmWalletClient.ts +1008 -0
- package/src/internal/publicClient.ts +0 -3
- package/src/promises/Payment.ts +26 -25
- package/src/promises/PublicClient.ts +2 -3
- package/src/promises/WalletClient.ts +0 -1
- package/src/rpc.ts +2 -4
- package/unionlabs-payments-0.3.1.tgz +0 -0
- package/src/tsdoc-metadata.json +0 -11
- /package/{constants → Constants}/ibc-core-registry/package.json +0 -0
- /package/{constants → Constants}/services/package.json +0 -0
- /package/{constants → Constants}/z-asset-registry/package.json +0 -0
package/src/WalletClient.ts
CHANGED
|
@@ -66,8 +66,8 @@ export interface WalletClient {
|
|
|
66
66
|
) => Effect.Effect<Domain.PreparedRequest, SdkError, never>;
|
|
67
67
|
|
|
68
68
|
readonly sign: (
|
|
69
|
-
request: Domain.PreparedRequest,
|
|
70
|
-
) => Effect.Effect<Domain.SignedRequest, SdkError, never>;
|
|
69
|
+
request: ReadonlyArray<Domain.PreparedRequest> | Domain.PreparedRequest,
|
|
70
|
+
) => Effect.Effect<Domain.SignedRequest[], SdkError, never>;
|
|
71
71
|
|
|
72
72
|
// TODO: can be done by public client (?)
|
|
73
73
|
readonly submit: (
|
|
@@ -94,7 +94,7 @@ export class SourceWalletClient extends Context.Tag("SourceWalletClient")<
|
|
|
94
94
|
SourceWalletClient,
|
|
95
95
|
WalletClient
|
|
96
96
|
>() {
|
|
97
|
-
static
|
|
97
|
+
static project = <E, R>(layer: Layer.Layer<WalletClient, E, R>) =>
|
|
98
98
|
Layer.project(layer, WalletClient, SourceWalletClient, identity);
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -105,7 +105,7 @@ export class SourceWalletClient extends Context.Tag("SourceWalletClient")<
|
|
|
105
105
|
export class DestinationWalletClient extends Context.Tag(
|
|
106
106
|
"DestinationWalletClient",
|
|
107
107
|
)<DestinationWalletClient, WalletClient>() {
|
|
108
|
-
static
|
|
108
|
+
static project = <E, R>(layer: Layer.Layer<WalletClient, E, R>) =>
|
|
109
109
|
Layer.project(layer, WalletClient, DestinationWalletClient, identity);
|
|
110
110
|
}
|
|
111
111
|
|
|
@@ -131,37 +131,41 @@ export namespace WalletClient {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
export interface ApproveZAssetToSpendErc20 {
|
|
134
|
+
universalChainId: Domain.UniversalChainId;
|
|
134
135
|
srcErc20Address: Domain.Erc20Address;
|
|
135
136
|
amount: bigint;
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
export interface UpdateLoopbackClient {
|
|
140
|
+
universalChainId: Domain.UniversalChainId;
|
|
139
141
|
clientId: number;
|
|
140
142
|
height: bigint;
|
|
141
|
-
ibcHandlerAddress: Domain.
|
|
143
|
+
ibcHandlerAddress: Domain.IbcCoreAddress;
|
|
142
144
|
}
|
|
143
145
|
|
|
144
146
|
export interface DepositUnderlyingZAsset {
|
|
147
|
+
universalChainId: Domain.UniversalChainId;
|
|
145
148
|
srcErc20Address: Domain.Erc20Address;
|
|
146
149
|
amount: bigint;
|
|
147
150
|
}
|
|
148
151
|
|
|
149
152
|
export interface TransferZAsset {
|
|
153
|
+
universalChainId: Domain.UniversalChainId;
|
|
150
154
|
srcErc20Address: Domain.Erc20Address;
|
|
151
155
|
depositAddress: `0x${string}`;
|
|
152
156
|
amount: bigint;
|
|
153
157
|
}
|
|
154
158
|
|
|
155
159
|
export type Deposit = {
|
|
160
|
+
destinationChainId: Domain.UniversalChainId;
|
|
156
161
|
srcErc20Address: Domain.Erc20Address;
|
|
157
|
-
sourceChainId: bigint;
|
|
158
162
|
readonly beneficiaries: ReadonlyArray<Address>;
|
|
159
163
|
depositAddress: Domain.ZAssetAddress;
|
|
160
|
-
destinationChainId: bigint;
|
|
161
164
|
amount: bigint;
|
|
162
165
|
};
|
|
163
166
|
|
|
164
167
|
export type Redeem = {
|
|
168
|
+
universalChainId: Domain.UniversalChainId;
|
|
165
169
|
dstErc20Address: Domain.Erc20Address;
|
|
166
170
|
unwrap?: boolean | undefined;
|
|
167
171
|
} & RedeemParams;
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Effect, flow, Option } from "effect";
|
|
2
2
|
import * as Domain from "../Domain.js";
|
|
3
3
|
import * as Error from "../Error.js";
|
|
4
4
|
|
|
5
|
-
export type ZAssetAddress = `0x${string}` & Brand.Brand<"ZAssetAddress">;
|
|
6
|
-
|
|
7
5
|
export const IBC_CORE_REGISTRY: {
|
|
8
|
-
[chainId:
|
|
6
|
+
[chainId: Domain.UniversalChainId]: Domain.IbcCoreAddress;
|
|
9
7
|
} = {
|
|
10
|
-
"8453": Domain.
|
|
8
|
+
[Domain.UniversalChainId.make("base.8453")]: Domain.IbcCoreAddress(
|
|
9
|
+
"0xee4ea8d358473f0fcebf0329feed95d56e8c04d7",
|
|
10
|
+
),
|
|
11
|
+
[Domain.UniversalChainId.make("ethereum.1")]: Domain.IbcCoreAddress(
|
|
11
12
|
"0xee4ea8d358473f0fcebf0329feed95d56e8c04d7",
|
|
12
13
|
),
|
|
13
14
|
} as const;
|
|
14
15
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
): Option.Option<Domain.
|
|
18
|
-
|
|
19
|
-
}
|
|
16
|
+
export const getIbcCoreAddress = (
|
|
17
|
+
ucid: Domain.UniversalChainId,
|
|
18
|
+
): Option.Option<Domain.IbcCoreAddress> =>
|
|
19
|
+
Option.fromNullable(IBC_CORE_REGISTRY[ucid]);
|
|
20
20
|
|
|
21
|
-
export const
|
|
22
|
-
|
|
21
|
+
export const getIbcCoreAddressOrError = flow(
|
|
22
|
+
getIbcCoreAddress,
|
|
23
23
|
Effect.mapError(
|
|
24
24
|
(cause) =>
|
|
25
25
|
new Error.SystemError({
|
|
@@ -31,8 +31,8 @@ export const getIbcHandlerOrError = flow(
|
|
|
31
31
|
),
|
|
32
32
|
);
|
|
33
33
|
|
|
34
|
-
export const
|
|
35
|
-
|
|
34
|
+
export const getIbcCoreAddressOrThrow = flow(
|
|
35
|
+
getIbcCoreAddress,
|
|
36
36
|
Option.getOrThrowWith(
|
|
37
37
|
() =>
|
|
38
38
|
new Error.SystemError({
|
|
@@ -4,22 +4,25 @@ import * as Domain from "../Domain.js";
|
|
|
4
4
|
import * as Error from "../Error.js";
|
|
5
5
|
|
|
6
6
|
export const Z_ASSET_REGISTRY: {
|
|
7
|
-
[chainId:
|
|
7
|
+
[chainId: Domain.UniversalChainId]: {
|
|
8
8
|
[assetAddress: Erc20Address]: Domain.ZAssetAddress;
|
|
9
9
|
};
|
|
10
10
|
} = {
|
|
11
|
-
"8453": {
|
|
11
|
+
[Domain.UniversalChainId.make("base.8453")]: {
|
|
12
12
|
[Domain.Erc20Address("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913")]:
|
|
13
13
|
Domain.ZAssetAddress("0xF0000101561619d8A61ABd045F47Af4f41Afe62D"),
|
|
14
14
|
},
|
|
15
|
+
[Domain.UniversalChainId.make("ethereum.1")]: {
|
|
16
|
+
[Domain.Erc20Address("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")]: // USDC on ethereum.1
|
|
17
|
+
Domain.ZAssetAddress("0xF0000101561619d8A61ABd045F47Af4f41Afe62D"),
|
|
18
|
+
},
|
|
15
19
|
} as const;
|
|
16
20
|
|
|
17
|
-
export
|
|
18
|
-
|
|
21
|
+
export const getZAsset = (
|
|
22
|
+
universalChainId: Domain.UniversalChainId,
|
|
19
23
|
assetAddress: Erc20Address,
|
|
20
|
-
): Option.Option<Domain.ZAssetAddress>
|
|
21
|
-
|
|
22
|
-
}
|
|
24
|
+
): Option.Option<Domain.ZAssetAddress> =>
|
|
25
|
+
Option.fromNullable(Z_ASSET_REGISTRY?.[universalChainId]?.[assetAddress]);
|
|
23
26
|
|
|
24
27
|
export const getZAssetOrError = flow(
|
|
25
28
|
getZAsset,
|
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
import * as Duration from "effect/Duration";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import { pipe } from "effect/Function";
|
|
4
|
+
import * as S from "effect/Schema";
|
|
5
|
+
import type * as Viem from "viem";
|
|
6
|
+
import { bytesToHex, hexToBytes } from "viem";
|
|
7
|
+
import * as Abi from "../Abi.js";
|
|
8
|
+
import * as ZAssetRegistry from "../constants/z-asset-registry.js";
|
|
9
|
+
import * as Domain from "../Domain.js";
|
|
10
|
+
import * as Error from "../Error.js";
|
|
11
|
+
import type * as EvmPublicClient from "../EvmPublicClient.js";
|
|
12
|
+
import * as Client from "../PublicClient.js";
|
|
13
|
+
import * as PS from "../Schema.js";
|
|
14
|
+
|
|
15
|
+
/** @internal */
|
|
16
|
+
export const TypeId: EvmPublicClient.TypeId = Symbol.for(
|
|
17
|
+
"@unionlabs/payments/EvmPublicClient",
|
|
18
|
+
) as EvmPublicClient.TypeId;
|
|
19
|
+
|
|
20
|
+
export const makeViem = (
|
|
21
|
+
client: Viem.PublicClient,
|
|
22
|
+
): Effect.Effect<EvmPublicClient.EvmPublicClient, Error.SdkError, never> =>
|
|
23
|
+
Effect.gen(function* () {
|
|
24
|
+
// const Viem = yield* Effect.tryPromise({
|
|
25
|
+
// try: () => import("viem").then((x) => x.default),
|
|
26
|
+
// catch: (cause) =>
|
|
27
|
+
// new Error.SystemError({
|
|
28
|
+
// reason: "DynamicImport",
|
|
29
|
+
// method: "makeViem",
|
|
30
|
+
// module: "EvmPublicClient",
|
|
31
|
+
// cause,
|
|
32
|
+
// description: "could not import viem",
|
|
33
|
+
// }),
|
|
34
|
+
// });
|
|
35
|
+
|
|
36
|
+
const readContract = Effect.fn("readContract")(
|
|
37
|
+
<
|
|
38
|
+
TAbi extends Viem.Abi,
|
|
39
|
+
A,
|
|
40
|
+
I,
|
|
41
|
+
R = never,
|
|
42
|
+
TFunctionName extends Viem.ContractFunctionName<
|
|
43
|
+
TAbi,
|
|
44
|
+
"pure" | "view"
|
|
45
|
+
> = Viem.ContractFunctionName<TAbi, "pure" | "view">,
|
|
46
|
+
TArgs extends Viem.ContractFunctionArgs<
|
|
47
|
+
TAbi,
|
|
48
|
+
"pure" | "view",
|
|
49
|
+
TFunctionName
|
|
50
|
+
> = Viem.ContractFunctionArgs<TAbi, "pure" | "view", TFunctionName>,
|
|
51
|
+
>(
|
|
52
|
+
params: Viem.ReadContractParameters<TAbi, TFunctionName, TArgs>,
|
|
53
|
+
schema: S.Schema<A, I, R>,
|
|
54
|
+
): Effect.Effect<A, Error.SdkError, R> =>
|
|
55
|
+
pipe(
|
|
56
|
+
Effect.tryPromise({
|
|
57
|
+
try: () => client.readContract(params),
|
|
58
|
+
catch: (cause) =>
|
|
59
|
+
new Error.SystemError({
|
|
60
|
+
method: "readContract",
|
|
61
|
+
module: "EvmPublicClient",
|
|
62
|
+
reason: "ReadContract",
|
|
63
|
+
cause,
|
|
64
|
+
}),
|
|
65
|
+
}),
|
|
66
|
+
Effect.flatMap(S.decodeUnknown(schema)),
|
|
67
|
+
Effect.catchTag(
|
|
68
|
+
"ParseError",
|
|
69
|
+
(cause) =>
|
|
70
|
+
new Error.SystemError({
|
|
71
|
+
method: "readContract",
|
|
72
|
+
module: "EvmPublicClient",
|
|
73
|
+
reason: "InvalidData",
|
|
74
|
+
cause,
|
|
75
|
+
}),
|
|
76
|
+
),
|
|
77
|
+
),
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const getLatestHeight = Effect.fn("getLatestHeight")(
|
|
81
|
+
(lightClientAddress: Domain.LightClientAddress, clientId: number) =>
|
|
82
|
+
readContract(
|
|
83
|
+
{
|
|
84
|
+
address: lightClientAddress,
|
|
85
|
+
abi: Abi.LIGHT_CLIENT_ABI,
|
|
86
|
+
functionName: "getLatestHeight",
|
|
87
|
+
args: [clientId],
|
|
88
|
+
},
|
|
89
|
+
S.BigIntFromSelf,
|
|
90
|
+
),
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const getLightClientAddress = Effect.fn("getLightClientAddress")(function* (
|
|
94
|
+
ibcStoreAddress: Domain.IbcCoreAddress,
|
|
95
|
+
clientId: number,
|
|
96
|
+
) {
|
|
97
|
+
const res = yield* readContract(
|
|
98
|
+
{
|
|
99
|
+
address: ibcStoreAddress,
|
|
100
|
+
abi: Abi.IBC_STORE_ABI,
|
|
101
|
+
functionName: "getClient",
|
|
102
|
+
args: [clientId],
|
|
103
|
+
},
|
|
104
|
+
PS.Hex,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
return Domain.LightClientAddress(res);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const getStateRootIndex = Effect.fn("getStateRootIndex")(
|
|
111
|
+
(zAssetAddress: Domain.ZAssetAddress, clientId: number) =>
|
|
112
|
+
readContract(
|
|
113
|
+
{
|
|
114
|
+
address: zAssetAddress,
|
|
115
|
+
abi: Abi.ZASSET_ABI,
|
|
116
|
+
functionName: "stateRootIndex",
|
|
117
|
+
args: [clientId],
|
|
118
|
+
},
|
|
119
|
+
S.BigIntFromSelf,
|
|
120
|
+
),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
const getConsensusState = Effect.fn("getConsensusState")(
|
|
124
|
+
(
|
|
125
|
+
lightClientAddress: Domain.LightClientAddress,
|
|
126
|
+
clientId: number,
|
|
127
|
+
height: bigint,
|
|
128
|
+
stateRootIndex: bigint,
|
|
129
|
+
) =>
|
|
130
|
+
pipe(
|
|
131
|
+
readContract(
|
|
132
|
+
{
|
|
133
|
+
address: lightClientAddress,
|
|
134
|
+
abi: Abi.LIGHT_CLIENT_ABI,
|
|
135
|
+
functionName: "getConsensusState",
|
|
136
|
+
args: [clientId, height],
|
|
137
|
+
},
|
|
138
|
+
PS.Hex,
|
|
139
|
+
),
|
|
140
|
+
// XXX: this can definitely fail
|
|
141
|
+
Effect.map((consensusBytes) => {
|
|
142
|
+
const bytes: Uint8Array = hexToBytes(consensusBytes);
|
|
143
|
+
const idx = Number(stateRootIndex);
|
|
144
|
+
const stateRoot = bytesToHex(bytes.slice(idx, idx + 32));
|
|
145
|
+
return { stateRoot } as const;
|
|
146
|
+
}),
|
|
147
|
+
),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const getIbcHandlerAddress = Effect.fn("getIbcHandlerAddress")(function* (
|
|
151
|
+
zAssetAddress: Domain.ZAssetAddress,
|
|
152
|
+
) {
|
|
153
|
+
return Domain.IbcCoreAddress(
|
|
154
|
+
yield* readContract(
|
|
155
|
+
{
|
|
156
|
+
address: zAssetAddress,
|
|
157
|
+
abi: Abi.ZASSET_ABI,
|
|
158
|
+
functionName: "ibcHandler",
|
|
159
|
+
},
|
|
160
|
+
PS.Hex,
|
|
161
|
+
),
|
|
162
|
+
);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const readZAssetTokenBalance = Effect.fn("readZAssetTokenBalance")(
|
|
166
|
+
(
|
|
167
|
+
tokenAddress: Domain.ZAssetAddress,
|
|
168
|
+
accountAddress: `0x${string}`,
|
|
169
|
+
blockNumber?: bigint,
|
|
170
|
+
) =>
|
|
171
|
+
readContract(
|
|
172
|
+
{
|
|
173
|
+
address: tokenAddress,
|
|
174
|
+
abi: [
|
|
175
|
+
{
|
|
176
|
+
inputs: [{ name: "account", type: "address" }],
|
|
177
|
+
name: "balanceOf",
|
|
178
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
179
|
+
stateMutability: "view",
|
|
180
|
+
type: "function",
|
|
181
|
+
},
|
|
182
|
+
] as const,
|
|
183
|
+
functionName: "balanceOf",
|
|
184
|
+
args: [accountAddress],
|
|
185
|
+
blockNumber,
|
|
186
|
+
},
|
|
187
|
+
S.BigIntFromSelf,
|
|
188
|
+
),
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const readNullifierBalance = Effect.fn("readNullifierBalance")(
|
|
192
|
+
(zAssetAddress: Domain.ZAssetAddress, nullifier: bigint) =>
|
|
193
|
+
readContract(
|
|
194
|
+
{
|
|
195
|
+
address: zAssetAddress,
|
|
196
|
+
abi: Abi.ZASSET_ABI,
|
|
197
|
+
functionName: "nullifierBalance",
|
|
198
|
+
args: [nullifier],
|
|
199
|
+
},
|
|
200
|
+
S.BigIntFromSelf,
|
|
201
|
+
),
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
const getLatestBlockNumber = Effect.tryPromise({
|
|
205
|
+
try: () => client.getBlockNumber(),
|
|
206
|
+
catch: (cause) =>
|
|
207
|
+
new Error.SystemError({
|
|
208
|
+
method: "getLatestBlockNumber",
|
|
209
|
+
module: "EvmPublicClient",
|
|
210
|
+
reason: "InvalidData",
|
|
211
|
+
cause,
|
|
212
|
+
}),
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const readBalanceAtHeight = Effect.fn("readBalanceAtHeight")(
|
|
216
|
+
(
|
|
217
|
+
opts: Client.PublicClient.ReadBalanceAtHeightOptions,
|
|
218
|
+
): Effect.Effect<
|
|
219
|
+
Client.PublicClient.BalanceAtHeightInfo,
|
|
220
|
+
Error.SdkError
|
|
221
|
+
> =>
|
|
222
|
+
Effect.gen(function* () {
|
|
223
|
+
const latestHeight = yield* getLatestBlockNumber;
|
|
224
|
+
|
|
225
|
+
const srcZAssetAddress = yield* ZAssetRegistry.getZAsset(
|
|
226
|
+
opts.srcChainId,
|
|
227
|
+
opts.srcErc20Address,
|
|
228
|
+
).pipe(
|
|
229
|
+
Effect.mapError(
|
|
230
|
+
(cause) =>
|
|
231
|
+
new Error.SystemError({
|
|
232
|
+
method: "readBalanceAtHeight",
|
|
233
|
+
module: "EvmPublicClient",
|
|
234
|
+
reason: "InvalidData",
|
|
235
|
+
cause,
|
|
236
|
+
}),
|
|
237
|
+
),
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
const dstZAssetAddress = yield* ZAssetRegistry.getZAsset(
|
|
241
|
+
opts.dstChainId,
|
|
242
|
+
opts.dstErc20Address,
|
|
243
|
+
).pipe(
|
|
244
|
+
Effect.mapError(
|
|
245
|
+
(cause) =>
|
|
246
|
+
new Error.SystemError({
|
|
247
|
+
method: "readBalanceAtHeight",
|
|
248
|
+
module: "EvmPublicClient",
|
|
249
|
+
reason: "InvalidData",
|
|
250
|
+
cause,
|
|
251
|
+
}),
|
|
252
|
+
),
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
const [balanceAtTip, confirmed, redeemed] = yield* Effect.all(
|
|
256
|
+
[
|
|
257
|
+
// ZAsset balance of the deposit address ZAsset on the source chain at the tip of the chain
|
|
258
|
+
readZAssetTokenBalance(
|
|
259
|
+
srcZAssetAddress,
|
|
260
|
+
opts.depositAddress,
|
|
261
|
+
latestHeight,
|
|
262
|
+
),
|
|
263
|
+
// ZAsset balance of the deposit address on the source chain at the (latest) light client height
|
|
264
|
+
readZAssetTokenBalance(
|
|
265
|
+
srcZAssetAddress,
|
|
266
|
+
opts.depositAddress,
|
|
267
|
+
opts.height,
|
|
268
|
+
),
|
|
269
|
+
// amount that has already been redeemed under the specified nullifier
|
|
270
|
+
readNullifierBalance(dstZAssetAddress, opts.nullifier),
|
|
271
|
+
],
|
|
272
|
+
{ concurrency: "unbounded" },
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
const available = confirmed > redeemed ? confirmed - redeemed : 0n;
|
|
276
|
+
const pending =
|
|
277
|
+
balanceAtTip > confirmed ? balanceAtTip - confirmed : 0n;
|
|
278
|
+
|
|
279
|
+
return { confirmed, redeemed, available, pending, latestHeight };
|
|
280
|
+
}),
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
const readBalance = Effect.fn("readBalance")(
|
|
284
|
+
(
|
|
285
|
+
opts: Client.PublicClient.ReadBalanceOptions,
|
|
286
|
+
): Effect.Effect<Client.PublicClient.BalanceInfo, Error.SdkError> =>
|
|
287
|
+
Effect.gen(function* () {
|
|
288
|
+
const dstZAssetAddress = yield* ZAssetRegistry.getZAsset(
|
|
289
|
+
opts.dstChainId,
|
|
290
|
+
opts.dstErc20Address,
|
|
291
|
+
).pipe(
|
|
292
|
+
Effect.mapError(
|
|
293
|
+
(cause) =>
|
|
294
|
+
new Error.SystemError({
|
|
295
|
+
method: "readBalance",
|
|
296
|
+
module: "EvmPublicClient",
|
|
297
|
+
reason: "InvalidData",
|
|
298
|
+
cause,
|
|
299
|
+
}),
|
|
300
|
+
),
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
yield* Effect.log({ opts, dstZAssetAddress });
|
|
304
|
+
|
|
305
|
+
const ibcHandlerAddress =
|
|
306
|
+
yield* getIbcHandlerAddress(dstZAssetAddress);
|
|
307
|
+
|
|
308
|
+
const lightClientAddress = yield* getLightClientAddress(
|
|
309
|
+
ibcHandlerAddress,
|
|
310
|
+
opts.clientId,
|
|
311
|
+
);
|
|
312
|
+
const lightClientHeight = yield* getLatestHeight(
|
|
313
|
+
lightClientAddress,
|
|
314
|
+
opts.clientId,
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
const balance = yield* readBalanceAtHeight({
|
|
318
|
+
srcErc20Address: opts.srcErc20Address,
|
|
319
|
+
srcChainId: opts.srcChainId,
|
|
320
|
+
dstErc20Address: opts.dstErc20Address,
|
|
321
|
+
dstChainId: opts.dstChainId,
|
|
322
|
+
depositAddress: opts.depositAddress,
|
|
323
|
+
nullifier: opts.nullifier,
|
|
324
|
+
height: lightClientHeight,
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
return { ...balance, lightClientHeight };
|
|
328
|
+
}),
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
const getCounterparty = Effect.fn("getCounterparty")(
|
|
332
|
+
(zAssetAddress: Domain.ZAssetAddress, clientId: number) =>
|
|
333
|
+
readContract(
|
|
334
|
+
{
|
|
335
|
+
address: zAssetAddress,
|
|
336
|
+
abi: Abi.ZASSET_ABI,
|
|
337
|
+
functionName: "counterparty",
|
|
338
|
+
args: [clientId],
|
|
339
|
+
},
|
|
340
|
+
Domain.CounterpartyInfo,
|
|
341
|
+
),
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
const getProof = Effect.fn("getProof")(
|
|
345
|
+
(options: {
|
|
346
|
+
address: `0x${string}`;
|
|
347
|
+
storageKeys: `0x${string}`[];
|
|
348
|
+
blockNumber: bigint;
|
|
349
|
+
}) =>
|
|
350
|
+
Effect.tryPromise({
|
|
351
|
+
try: () => client.getProof(options),
|
|
352
|
+
catch: (cause) =>
|
|
353
|
+
new Error.SystemError({
|
|
354
|
+
method: "getProof",
|
|
355
|
+
module: "EvmPublicClient",
|
|
356
|
+
reason: "InvalidData",
|
|
357
|
+
cause,
|
|
358
|
+
}),
|
|
359
|
+
}),
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
const waitForTransactionReceipt = Effect.fn("waitForTransactionReceipt")(
|
|
363
|
+
(hash: Domain.TxHash) =>
|
|
364
|
+
pipe(
|
|
365
|
+
Effect.tryPromise({
|
|
366
|
+
try: () => client.waitForTransactionReceipt({ hash }),
|
|
367
|
+
catch: (cause) =>
|
|
368
|
+
new Error.SystemError({
|
|
369
|
+
method: "waitForTransactionReceipt",
|
|
370
|
+
module: "EvmPublicClient",
|
|
371
|
+
reason: "InvalidData",
|
|
372
|
+
cause,
|
|
373
|
+
}),
|
|
374
|
+
}),
|
|
375
|
+
Effect.flatMap((x) =>
|
|
376
|
+
x.status === "success"
|
|
377
|
+
? Effect.succeed(x)
|
|
378
|
+
: Effect.fail(
|
|
379
|
+
new Error.SystemError({
|
|
380
|
+
method: "waitForTransactionReceipt",
|
|
381
|
+
module: "EvmPublicClient",
|
|
382
|
+
reason: "InvalidData",
|
|
383
|
+
description: "contract reverted",
|
|
384
|
+
}),
|
|
385
|
+
),
|
|
386
|
+
),
|
|
387
|
+
),
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
const waitForBlock = Effect.fn("waitForBlock")(
|
|
391
|
+
(targetHeight: bigint): Effect.Effect<bigint, Error.SdkError> =>
|
|
392
|
+
pipe(
|
|
393
|
+
getLatestBlockNumber,
|
|
394
|
+
Effect.flatMap((initial) =>
|
|
395
|
+
Effect.iterate(initial, {
|
|
396
|
+
// one block extra to avoid loadbalancer issues
|
|
397
|
+
while: (height) => height <= targetHeight,
|
|
398
|
+
body: () =>
|
|
399
|
+
pipe(
|
|
400
|
+
Effect.sleep(Duration.seconds(1)),
|
|
401
|
+
Effect.andThen(getLatestBlockNumber),
|
|
402
|
+
),
|
|
403
|
+
}),
|
|
404
|
+
),
|
|
405
|
+
),
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
const simulateCalls = Effect.fn("simulateCalls")(
|
|
409
|
+
(params: {
|
|
410
|
+
calls: Array<{
|
|
411
|
+
to: `0x${string}`;
|
|
412
|
+
data: `0x${string}`;
|
|
413
|
+
value?: bigint | undefined;
|
|
414
|
+
}>;
|
|
415
|
+
account?: `0x${string}` | undefined;
|
|
416
|
+
}) =>
|
|
417
|
+
Effect.tryPromise({
|
|
418
|
+
try: async () => {
|
|
419
|
+
const { simulateCalls } = await import("viem/actions");
|
|
420
|
+
return simulateCalls(client, {
|
|
421
|
+
calls: params.calls.map((call) => ({
|
|
422
|
+
to: call.to,
|
|
423
|
+
data: call.data,
|
|
424
|
+
value: call.value,
|
|
425
|
+
})),
|
|
426
|
+
account: params.account,
|
|
427
|
+
});
|
|
428
|
+
},
|
|
429
|
+
catch: (cause) =>
|
|
430
|
+
new Error.SystemError({
|
|
431
|
+
method: "simulateCalls",
|
|
432
|
+
module: "EvmPublicClient",
|
|
433
|
+
reason: "InvalidData",
|
|
434
|
+
cause,
|
|
435
|
+
}),
|
|
436
|
+
}),
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
return Object.assign(
|
|
440
|
+
yield* Client.make({
|
|
441
|
+
getLatestHeight,
|
|
442
|
+
getLatestBlockNumber,
|
|
443
|
+
readBalance,
|
|
444
|
+
readBalanceAtHeight,
|
|
445
|
+
getLightClientAddress,
|
|
446
|
+
getStateRootIndex,
|
|
447
|
+
getConsensusState,
|
|
448
|
+
getIbcHandlerAddress,
|
|
449
|
+
getCounterparty,
|
|
450
|
+
getProof,
|
|
451
|
+
waitForBlock,
|
|
452
|
+
}),
|
|
453
|
+
{
|
|
454
|
+
[TypeId]: TypeId as EvmPublicClient.TypeId,
|
|
455
|
+
waitForTransactionReceipt,
|
|
456
|
+
simulateCalls,
|
|
457
|
+
},
|
|
458
|
+
);
|
|
459
|
+
});
|