-
Notifications
You must be signed in to change notification settings - Fork 1
/
contract.ts
309 lines (243 loc) · 8.06 KB
/
contract.ts
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
// Import ethers from ethers.js
import { ethers, Signer, Contract, BrowserProvider } from 'ethers';
import contractABI from './ABI.json';
export const contractAddress = '0xDCc49e76b061db2AA11013cB47f5D9ebfC131361';
// Declare global variables for provider, signer, and contract
let provider: BrowserProvider | null;
let signer: Signer | null;
let contract: Contract | null;
// Function to initialize provider and signer asynchronously
async function initializeProviderAndSigner() {
try {
if (typeof window.ethereum !== 'undefined') {
provider = new ethers.BrowserProvider(window.ethereum);
await window.ethereum.request({ method: "eth_requestAccounts" });
signer = await provider.getSigner();
contract = new ethers.Contract(contractAddress, contractABI, signer);
} else {
console.warn('MetaMask or Web3 provider not found. Please install or enable it.');
provider = null;
signer = null;
contract = null;
}
} catch (error) {
console.error('Error initializing Web3 provider:', error);
provider = null;
signer = null;
contract = null;
}
}
// Call the function to initialize provider and signer
void initializeProviderAndSigner();
// Create a contract instance with a signer, which enables sending transactions
// const contract = new ethers.Contract(contractAddress, contractABI, signer);
export async function getAccount(): Promise<string> {
if (provider && signer)
try {
await provider.send("eth_requestAccounts", []);
const account = await signer.getAddress();
if (!account) {
console.error("No accessible accounts. Make sure MetaMask is connected.");
return '';
}
return account;
} catch (error) {
console.error("Could not get access to accounts:", error);
return '';
}
return '';
}
// token details to improve readability and maintainability
export interface TokenDetails {
tokenId: number;
cidHash: string;
}
async function getEvent(
tx: any,
eventName: string,
) {
const receipt = await tx.wait();
if (receipt?.logs) {
for (const log of receipt.logs) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const event = contract?.interface.parseLog(log);
if (event?.name === eventName) {
return event;
}
}
}
return null;
}
export async function mintToken(cidHash: string, encryptedFileKey: Uint8Array[]): Promise<TokenDetails> {
try {
const txResponse = await contract?.mintToken(cidHash, encryptedFileKey);
const tokenMintedEvent = await getEvent(txResponse, 'TokenMinted');
if (!tokenMintedEvent) throw new Error('TokenMinted event not found.');
const tokenId = Number(tokenMintedEvent.args[0]);
return { tokenId: tokenId, cidHash: cidHash };
} catch (error) {
console.error('Error in contract.mintToken:', error);
throw error;
}
}
/**
* Fetches a specific number of tokens starting from the given index.
*
* @param start The starting index to fetch tokens.
* @param count The number of tokens to fetch starting from the `start` index.
* @returns An array of `TokenDetails` containing token IDs and their cidHashs.
*/
export async function getTokensInRange(start: number, count: number): Promise<TokenDetails[]> {
try {
// Use the start index and count to determine the range to fetch
const end = start + count;
// Call the smart contract to fetch tokens in this range
const result = await contract?.getTokensInRange(start, end);
// Expect result to be an array of arrays: [token IDs, cidHashs]
const tokenIds: number[] = result[0];
const cidHashs: string[] = result[1];
// Map token IDs to their corresponding cidHashs to form an array of TokenDetails
const tokens: TokenDetails[] = tokenIds.map((tokenId, index) => ({
tokenId,
cidHash: cidHashs[index]
}));
return tokens;
} catch (error) {
console.error('Error contract.getTokensInRange:', error);
return [];
}
}
export async function getSharedTokensInRange(start: number, count: number): Promise<TokenDetails[]> {
try {
// Calculate the end index based on the start index and the number of tokens to fetch
const end = start + count;
// Call the smart contract to fetch shared tokens within the specified range
const result = await contract?.getSharedTokensInRange(start, end);
// Expect result to be an array of arrays: [token IDs, cidHashs]
const tokenIds: number[] = result[0];
const cidHashs: string[] = result[1];
// Map token IDs to their corresponding CID hashes to create an array of TokenDetails
const tokens: TokenDetails[] = tokenIds.map((tokenId, index) => ({
tokenId,
cidHash: cidHashs[index]
}));
return tokens;
} catch (error) {
console.error('Error in fetching shared tokens:', error);
return [];
}
}
export async function getSharedWithAddresses(tokenId: number): Promise<string[]> {
try {
const addresses: string[] = await contract?.getSharedWithAddresses(tokenId);
return addresses;
} catch (error) {
console.error('Error fetching shared addresses:', error);
return [];
}
}
export async function transferToken(to: string, tokenId: number): Promise<boolean> {
try {
// Call the contract's transferToken function
const tx = await contract?.transferToken(to, tokenId);
// Wait for transaction confirmation
await tx.wait();
return true;
} catch (error) {
console.error('Error transferring token:', error);
return false;
}
}
export async function shareToken(to: string, tokenId: number): Promise<boolean> {
try {
// Ensure the array is not empty
if (to.length === 0) {
throw new Error('Recipient list cannot be empty.');
}
// Call the contract's `shareToken` function with the array of addresses
const tx = await contract?.shareToken(tokenId, to);
// Wait for the transaction to confirm
await tx.wait();
return true;
} catch (error) {
console.error('Error contract.shareToken:', error);
return false;
}
}
export async function burnToken(tokenId: number, limitNumberOfSharedWith: number): Promise<boolean> {
try {
// Call the contract's burnToken function
const tx = await contract?.burnToken(tokenId, limitNumberOfSharedWith);
console.log('Transaction hash:', tx.hash);
// Wait for transaction confirmation
await tx.wait();
return true;
} catch (error) {
console.error('Error contract.burnToken :', error);
return false;
}
}
export async function getSupply(): Promise<number> {
try {
const totalNFTs = await contract?.getSupply();
return Number(totalNFTs);
} catch (error) {
console.error("Failed to fetch the total number of NFTs:", error);
throw error;
}
}
export async function getSharedWithSupply(): Promise<number> {
try {
const totalSharedWithNFTs = await contract?.getSharedWithSupply();
return Number(totalSharedWithNFTs);
} catch (error) {
console.error("Failed to fetch the total number of NFTs shared: ", error);
throw error;
}
}
export async function reencrypt(tokenId: number,
publicKey: Uint8Array,
signature: string,
): Promise<string[]> {
try {
const data: string[] = await contract?.reencrypt(tokenId, publicKey, signature);
if (!data) {
console.error('No return for contract.reencrypt');
return [];
}
return data;
} catch (error) {
console.error('Error fetching contract.reencrypt :', error);
return [];
}
}
export async function revokeTokenAccess(tokenId: number, userAddress: string): Promise<boolean> {
try {
const tx = await contract?.revokeTokenAccess(tokenId, userAddress);
await tx.wait();
return true;
} catch (error) {
console.error('Error revoking access:', error);
return false;
}
}
export async function revokeAllSharedAccess(tokenId: number, limitNumberOfSharedWith: number): Promise<boolean> {
try {
const tx = await contract?.revokeAllSharedAccess(tokenId, limitNumberOfSharedWith);
await tx.wait();
return true;
} catch (error) {
console.error('Error revoking all shared access:', error);
return false;
}
}
// Function to get the MAX_USERS_TO_REMOVE value
export async function getMaxUsersToRemove(): Promise<number> {
try {
const maxUsersToRemove: number = await contract?.MAX_USERS_TO_REMOVE();
return maxUsersToRemove;
} catch (error) {
console.error("Error fetching MAX_USERS_TO_REMOVE:", error);
return 0;
}
}