-
Notifications
You must be signed in to change notification settings - Fork 72
Expand file tree
/
Copy pathipAccount.ts
More file actions
198 lines (187 loc) · 6.55 KB
/
ipAccount.ts
File metadata and controls
198 lines (187 loc) · 6.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import { Address, Hex, encodeFunctionData, PublicClient } from "viem";
import {
IPAccountExecuteRequest,
IPAccountExecuteResponse,
IPAccountExecuteWithSigRequest,
IPAccountExecuteWithSigResponse,
IpAccountStateResponse,
SetIpMetadataRequest,
TokenResponse,
} from "../types/resources/ipAccount";
import { handleError } from "../utils/errors";
import {
coreMetadataModuleAbi,
coreMetadataModuleAddress,
IpAccountImplClient,
SimpleWalletClient,
} from "../abi/generated";
import { getAddress, validateAddress } from "../utils/utils";
import { ChainIds } from "../types/config";
export class IPAccountClient {
private readonly wallet: SimpleWalletClient;
private readonly rpcClient: PublicClient;
private readonly chainId: ChainIds;
constructor(rpcClient: PublicClient, wallet: SimpleWalletClient, chainId: ChainIds) {
this.wallet = wallet;
this.rpcClient = rpcClient;
this.chainId = chainId;
}
/** Executes a transaction from the IP Account.
* @param request - The request object containing necessary data to execute IP Account a transaction.
* @param request.ipId The Ip Id to get ip account.
* @param request.to The recipient of the transaction.
* @param request.value The amount of Ether to send.
* @param request.accountAddress The ipId to send.
* @param request.data The data to send along with the transaction.
* @param request.txOptions - [Optional] transaction. This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns Tx hash for the transaction.
*/
public async execute(request: IPAccountExecuteRequest): Promise<IPAccountExecuteResponse> {
try {
const ipAccountClient = new IpAccountImplClient(
this.rpcClient,
this.wallet,
getAddress(request.ipId, "request.ipId"),
);
const req = {
to: request.to,
value: BigInt(0),
data: request.data,
};
if (request.txOptions?.encodedTxDataOnly) {
return { encodedTxData: ipAccountClient.executeEncode({ ...req, operation: 0 }) };
} else {
const txHash = await ipAccountClient.execute({ ...req, operation: 0 });
if (request.txOptions?.waitForTransaction) {
await this.rpcClient.waitForTransactionReceipt({
...request.txOptions,
hash: txHash,
});
}
return { txHash: txHash };
}
} catch (error) {
handleError(error, "Failed to execute the IP Account transaction");
}
}
/** Executes a transaction from the IP Account.
* @param request - The request object containing necessary data to execute IP Account a transaction.
* @param request.ipId The Ip Id to get ip account.
* @param request.to The recipient of the transaction.
* @param request.data The data to send along with the transaction.
* @param request.signer The signer of the transaction.
* @param request.deadline The deadline of the transaction signature.
* @param request.signature The signature of the transaction, EIP-712 encoded.
* @param request.value [Optional] The amount of Ether to send.
* @param request.txOptions [Optional] This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns Tx hash for the transaction.
*/
public async executeWithSig(
request: IPAccountExecuteWithSigRequest,
): Promise<IPAccountExecuteWithSigResponse> {
try {
const ipAccountClient = new IpAccountImplClient(
this.rpcClient,
this.wallet,
getAddress(request.ipId, "request.ipId"),
);
const req = {
to: getAddress(request.to, "request.to"),
value: BigInt(request.value || 0),
data: request.data,
signer: getAddress(request.signer, "request.signer"),
deadline: BigInt(request.deadline),
signature: request.signature,
};
if (request.txOptions?.encodedTxDataOnly) {
return { encodedTxData: ipAccountClient.executeWithSigEncode(req) };
} else {
const txHash = await ipAccountClient.executeWithSig(req);
if (request.txOptions?.waitForTransaction) {
await this.rpcClient.waitForTransactionReceipt({
...request.txOptions,
hash: txHash,
});
}
return { txHash: txHash };
}
} catch (error) {
handleError(error, "Failed to execute with signature for the IP Account transaction");
}
}
/** Returns the IPAccount's internal nonce for transaction ordering.
* @param ipId The IP ID
* @returns A Promise that resolves to the IP Account's nonce.
*/
public async getIpAccountNonce(ipId: Address): Promise<IpAccountStateResponse> {
try {
const ipAccount = new IpAccountImplClient(
this.rpcClient,
this.wallet,
getAddress(ipId, "ipId"),
);
const { result: state } = await ipAccount.state();
return state;
} catch (error) {
handleError(error, "Failed to get the IP Account nonce");
}
}
/**
* Returns the identifier of the non-fungible token which owns the account
* @returns A Promise that resolves to an object containing the chain ID, token contract address, and token ID.
*/
public async getToken(ipId: Address): Promise<TokenResponse> {
try {
const ipAccount = new IpAccountImplClient(
this.rpcClient,
this.wallet,
getAddress(ipId, "ipId"),
);
const [chainId, tokenContract, tokenId] = await ipAccount.token();
return {
chainId,
tokenContract,
tokenId,
};
} catch (error) {
handleError(error, "Failed to get the token");
}
}
/**
* Sets the metadataURI for an IP asset.
*/
public async setIpMetadata({
ipId,
metadataURI,
metadataHash,
txOptions,
}: SetIpMetadataRequest): Promise<Hex> {
try {
const data = encodeFunctionData({
abi: coreMetadataModuleAbi,
functionName: "setMetadataURI",
args: [validateAddress(ipId), metadataURI, metadataHash],
});
const { txHash } = await this.execute({
ipId: ipId,
to: coreMetadataModuleAddress[this.chainId],
data: data,
value: 0,
txOptions: {
...txOptions,
encodedTxDataOnly: false,
},
});
return txHash!;
} catch (error) {
handleError(
new Error(
(error as Error).message
.replace("Failed to execute the IP Account transaction: ", "")
.trim(),
),
"Failed to set the IP metadata",
);
}
}
}