@aboutcircles/sdk 0.1.10 → 0.1.11
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/Sdk.d.ts +5 -8
- package/dist/Sdk.d.ts.map +1 -1
- package/dist/Sdk.js +10 -35
- package/dist/avatars/HumanAvatar.d.ts +60 -108
- package/dist/avatars/HumanAvatar.d.ts.map +1 -1
- package/dist/avatars/HumanAvatar.js +72 -191
- package/dist/index.js +6027 -7345
- package/package.json +2 -1
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { ValidationError } from '@aboutcircles/sdk-utils';
|
|
2
2
|
import { SdkError } from '../errors';
|
|
3
3
|
import { BaseGroupContract } from '@aboutcircles/sdk-core';
|
|
4
|
-
import { encodeAbiParameters, parseAbiParameters, encodeFunctionData } from 'viem';
|
|
5
|
-
import { referralsModuleAbi } from '@aboutcircles/sdk-abis';
|
|
6
|
-
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
7
4
|
import { CommonAvatar } from './CommonAvatar';
|
|
5
|
+
import { Invitations, InviteFarm } from '@aboutcircles/sdk-invitations';
|
|
8
6
|
/**
|
|
9
7
|
* HumanAvatar class implementation
|
|
10
8
|
* Provides a simplified, user-friendly wrapper around Circles protocol for human avatars
|
|
@@ -96,250 +94,133 @@ export class HumanAvatar extends CommonAvatar {
|
|
|
96
94
|
// ============================================================================
|
|
97
95
|
// Trust methods are inherited from CommonAvatar
|
|
98
96
|
// ============================================================================
|
|
99
|
-
// Invitation methods
|
|
100
|
-
|
|
97
|
+
// Invitation methods using the new Invitations module
|
|
98
|
+
invitation = {
|
|
101
99
|
/**
|
|
102
|
-
*
|
|
100
|
+
* Get a referral code for inviting a new user who doesn't have a Safe wallet yet
|
|
103
101
|
*
|
|
104
|
-
* This
|
|
105
|
-
* 1.
|
|
106
|
-
* 2.
|
|
102
|
+
* This function:
|
|
103
|
+
* 1. Generates a new private key and signer address for the invitee
|
|
104
|
+
* 2. Finds proxy inviters (intermediaries in trust graph)
|
|
105
|
+
* 3. Builds transaction batch to transfer 96 CRC to the invitation module
|
|
106
|
+
* 4. Saves the referral data to the backend
|
|
107
|
+
* 5. Returns transactions and the generated private key
|
|
107
108
|
*
|
|
108
|
-
* The
|
|
109
|
+
* The private key should be shared with the invitee to claim their account.
|
|
109
110
|
*
|
|
110
111
|
* Requirements:
|
|
111
|
-
* - You must have at least
|
|
112
|
-
* -
|
|
113
|
-
* - You can only have one active invitation per invitee
|
|
112
|
+
* - You must have at least 96 CRC available (directly or via proxy inviters)
|
|
113
|
+
* - Referrals service must be configured
|
|
114
114
|
*
|
|
115
|
-
* @
|
|
116
|
-
* @returns Transaction response
|
|
115
|
+
* @returns Object containing transactions to execute and the private key to share
|
|
117
116
|
*
|
|
118
117
|
* @example
|
|
119
118
|
* ```typescript
|
|
120
|
-
*
|
|
121
|
-
*
|
|
119
|
+
* const { transactions, privateKey } = await avatar.invitation.getReferralCode();
|
|
120
|
+
* // Execute transactions
|
|
121
|
+
* await avatar.runner.sendTransaction(transactions);
|
|
122
|
+
* // Share privateKey with invitee
|
|
122
123
|
* ```
|
|
123
124
|
*/
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const trustTx = this.core.hubV2.trust(invitee, BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFF'));
|
|
128
|
-
// Get the token ID for this avatar's personal token
|
|
129
|
-
const tokenId = await this.core.hubV2.toTokenId(this.address);
|
|
130
|
-
// ABI-encode the invitee address as 32 bytes
|
|
131
|
-
const encodedInvitee = encodeAbiParameters(parseAbiParameters('address'), [invitee]);
|
|
132
|
-
// Create the safeTransferFrom transaction to the InvitationEscrow contract
|
|
133
|
-
const transferTx = this.core.hubV2.safeTransferFrom(this.address, this.core.config.invitationEscrowAddress, tokenId, BigInt(100e18), encodedInvitee);
|
|
134
|
-
// Batch both transactions: trust + invitation transfer
|
|
135
|
-
return await this.runner.sendTransaction([trustTx, transferTx]);
|
|
125
|
+
getReferralCode: async () => {
|
|
126
|
+
const invitations = new Invitations(this.core.config);
|
|
127
|
+
return await invitations.generateReferral(this.address);
|
|
136
128
|
},
|
|
137
129
|
/**
|
|
138
|
-
*
|
|
130
|
+
* Invite a user who already has a Safe wallet but is not yet registered in Circles
|
|
139
131
|
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
132
|
+
* Use this when inviting someone who has an existing Safe wallet but is not
|
|
133
|
+
* yet registered in Circles Hub.
|
|
142
134
|
*
|
|
143
|
-
* @param invitee
|
|
144
|
-
* @returns
|
|
135
|
+
* @param invitee Address of the invitee (must have existing Safe wallet, NOT registered in Circles)
|
|
136
|
+
* @returns Array of transactions to execute
|
|
145
137
|
*
|
|
146
138
|
* @example
|
|
147
139
|
* ```typescript
|
|
148
|
-
* await avatar.invite
|
|
140
|
+
* const transactions = await avatar.invitation.invite('0xInviteeAddress');
|
|
141
|
+
* await avatar.runner.sendTransaction(transactions);
|
|
149
142
|
* ```
|
|
150
143
|
*/
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
return await this.
|
|
144
|
+
invite: async (invitee) => {
|
|
145
|
+
const invitations = new Invitations(this.core.config);
|
|
146
|
+
return await invitations.generateInvite(this.address, invitee);
|
|
154
147
|
},
|
|
155
148
|
/**
|
|
156
|
-
*
|
|
149
|
+
* Get proxy inviters who can facilitate invitations
|
|
157
150
|
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
151
|
+
* Proxy inviters are addresses that:
|
|
152
|
+
* - Trust this avatar (or have mutual trust)
|
|
153
|
+
* - Are trusted by the invitation module
|
|
154
|
+
* - Have sufficient balance to cover invitation fees (96 CRC per invite)
|
|
160
155
|
*
|
|
161
|
-
* @returns
|
|
156
|
+
* @returns Array of proxy inviters with their addresses and possible invite counts
|
|
162
157
|
*
|
|
163
158
|
* @example
|
|
164
159
|
* ```typescript
|
|
165
|
-
* await avatar.
|
|
166
|
-
*
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const revokeAllTx = this.core.invitationEscrow.revokeAllInvitations();
|
|
170
|
-
return await this.runner.sendTransaction([revokeAllTx]);
|
|
171
|
-
},
|
|
172
|
-
/**
|
|
173
|
-
* Redeem an invitation received from an inviter
|
|
174
|
-
*
|
|
175
|
-
* This claims the escrowed tokens from a specific inviter and refunds
|
|
176
|
-
* all other inviters' escrows back to them.
|
|
177
|
-
*
|
|
178
|
-
* @param inviter The address of the inviter whose invitation to redeem
|
|
179
|
-
* @returns Transaction response
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* ```typescript
|
|
183
|
-
* // Get all inviters first
|
|
184
|
-
* const inviters = await avatar.invite.getInviters();
|
|
185
|
-
*
|
|
186
|
-
* // Redeem invitation from the first inviter
|
|
187
|
-
* await avatar.invite.redeem(inviters[0]);
|
|
188
|
-
* ```
|
|
189
|
-
*/
|
|
190
|
-
// @todo check if it functionable
|
|
191
|
-
redeem: async (inviter) => {
|
|
192
|
-
const redeemTx = this.core.invitationEscrow.redeemInvitation(inviter);
|
|
193
|
-
return await this.runner.sendTransaction([redeemTx]);
|
|
194
|
-
},
|
|
195
|
-
/**
|
|
196
|
-
* Get all addresses that have sent invitations to you
|
|
197
|
-
*
|
|
198
|
-
* @returns Array of inviter addresses
|
|
199
|
-
*
|
|
200
|
-
* @example
|
|
201
|
-
* ```typescript
|
|
202
|
-
* const inviters = await avatar.invite.getInviters();
|
|
203
|
-
* console.log(`You have ${inviters.length} pending invitations`);
|
|
160
|
+
* const proxyInviters = await avatar.invitation.getProxyInviters();
|
|
161
|
+
* proxyInviters.forEach(inviter => {
|
|
162
|
+
* console.log(`${inviter.address}: can invite ${inviter.possibleInvites} people`);
|
|
163
|
+
* });
|
|
204
164
|
* ```
|
|
205
165
|
*/
|
|
206
|
-
|
|
207
|
-
|
|
166
|
+
getProxyInviters: async () => {
|
|
167
|
+
const invitations = new Invitations(this.core.config);
|
|
168
|
+
return await invitations.getRealInviters(this.address);
|
|
208
169
|
},
|
|
209
170
|
/**
|
|
210
|
-
*
|
|
171
|
+
* Find a path from this avatar to the invitation module
|
|
211
172
|
*
|
|
212
|
-
* @
|
|
173
|
+
* @param proxyInviterAddress Optional specific proxy inviter to route through
|
|
174
|
+
* @returns PathfindingResult containing the transfer path
|
|
213
175
|
*
|
|
214
176
|
* @example
|
|
215
177
|
* ```typescript
|
|
216
|
-
* const
|
|
217
|
-
* console.log(
|
|
178
|
+
* const path = await avatar.invitation.findInvitePath();
|
|
179
|
+
* console.log('Max flow:', path.maxFlow);
|
|
218
180
|
* ```
|
|
219
181
|
*/
|
|
220
|
-
|
|
221
|
-
|
|
182
|
+
findInvitePath: async (proxyInviterAddress) => {
|
|
183
|
+
const invitations = new Invitations(this.core.config);
|
|
184
|
+
return await invitations.findInvitePath(this.address, proxyInviterAddress);
|
|
222
185
|
},
|
|
223
186
|
/**
|
|
224
|
-
*
|
|
187
|
+
* Compute the deterministic Safe address for a given signer
|
|
225
188
|
*
|
|
226
|
-
*
|
|
189
|
+
* Uses CREATE2 to predict the Safe address without deployment.
|
|
227
190
|
*
|
|
228
|
-
* @param
|
|
229
|
-
* @
|
|
230
|
-
* @returns Object with escrowedAmount (in atto-circles) and days since escrow
|
|
191
|
+
* @param signer The signer public address
|
|
192
|
+
* @returns The deterministic Safe address
|
|
231
193
|
*
|
|
232
194
|
* @example
|
|
233
195
|
* ```typescript
|
|
234
|
-
*
|
|
235
|
-
* const { escrowedAmount, days_ } = await avatar.invite.getEscrowedAmount(
|
|
236
|
-
* avatar.address,
|
|
237
|
-
* '0xinvitee...'
|
|
238
|
-
* );
|
|
239
|
-
* console.log(`Escrowed: ${CirclesConverter.attoCirclesToCircles(escrowedAmount)} CRC`);
|
|
240
|
-
* console.log(`Days since escrow: ${days_}`);
|
|
241
|
-
*
|
|
242
|
-
* // Check an invitation you received
|
|
243
|
-
* const { escrowedAmount, days_ } = await avatar.invite.getEscrowedAmount(
|
|
244
|
-
* '0xinviter...',
|
|
245
|
-
* avatar.address
|
|
246
|
-
* );
|
|
196
|
+
* const safeAddress = avatar.invitation.computeAddress('0xSignerAddress');
|
|
247
197
|
* ```
|
|
248
198
|
*/
|
|
249
|
-
|
|
250
|
-
|
|
199
|
+
computeAddress: (signer) => {
|
|
200
|
+
const invitations = new Invitations(this.core.config);
|
|
201
|
+
return invitations.computeAddress(signer);
|
|
251
202
|
},
|
|
252
203
|
/**
|
|
253
|
-
* Generate new invitations
|
|
254
|
-
*
|
|
255
|
-
* This function:
|
|
256
|
-
* 1. Calls invitationFarm.claimInvites() to get invitation IDs via eth_call
|
|
257
|
-
* 2. Generates random secrets for each invitation
|
|
258
|
-
* 3. Derives signer addresses from the secrets using ECDSA
|
|
259
|
-
* 4. Batches the claimInvites write call with safeBatchTransferFrom to transfer
|
|
260
|
-
* invitation tokens (96 CRC each) to the invitation module
|
|
261
|
-
* 5. Returns the list of secrets and corresponding signers
|
|
262
|
-
*
|
|
263
|
-
* The data field in the batch transfer contains the count of generated secrets,
|
|
264
|
-
* which the contract uses to validate the transfer.
|
|
204
|
+
* Generate new invitations using the InvitationFarm
|
|
265
205
|
*
|
|
266
|
-
* @param
|
|
267
|
-
* @returns Promise containing
|
|
268
|
-
*
|
|
269
|
-
* @throws {SdkError} If the transaction fails or invitations cannot be claimed
|
|
206
|
+
* @param count Number of invitations to generate
|
|
207
|
+
* @returns Promise containing secrets, signers, and transaction receipt
|
|
270
208
|
*
|
|
271
209
|
* @example
|
|
272
210
|
* ```typescript
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
* console.log('Generated invitations:');
|
|
277
|
-
* result.secrets.forEach((secret, index) => {
|
|
278
|
-
* console.log(`Invitation ${index + 1}:`);
|
|
279
|
-
* console.log(` Secret: ${secret}`);
|
|
280
|
-
* console.log(` Signer: ${result.signers[index]}`);
|
|
211
|
+
* const result = await avatar.invitation.generateInvites(5);
|
|
212
|
+
* result.secrets.forEach((secret, i) => {
|
|
213
|
+
* console.log(`Invite ${i + 1}: ${result.signers[i]}`);
|
|
281
214
|
* });
|
|
282
215
|
* ```
|
|
283
216
|
*/
|
|
284
|
-
generateInvites: async (
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
// Step 1: Call eth_call to claimInvites to get invitation IDs (read-only simulation)
|
|
289
|
-
// This simulates the claimInvites call without actually modifying state
|
|
290
|
-
// to get the IDs that would be returned
|
|
291
|
-
const ids = (await this.core.invitationFarm.read('claimInvites', [numberOfInvites], {
|
|
292
|
-
from: this.address
|
|
293
|
-
}));
|
|
294
|
-
console.log("ids", ids);
|
|
295
|
-
if (!ids || ids.length === 0) {
|
|
296
|
-
throw SdkError.operationFailed('generateInvites', 'No invitation IDs returned from claimInvites');
|
|
297
|
-
}
|
|
298
|
-
// Step 2: Generate random secrets and derive signers
|
|
299
|
-
const secrets = [];
|
|
300
|
-
const signers = [];
|
|
301
|
-
for (let i = 0; i < numberOfInvites; i++) {
|
|
302
|
-
// Generate a random private key
|
|
303
|
-
const privateKey = generatePrivateKey();
|
|
304
|
-
secrets.push(privateKey);
|
|
305
|
-
// Derive the signer address from the private key
|
|
306
|
-
const account = privateKeyToAccount(privateKey);
|
|
307
|
-
signers.push(account.address.toLowerCase());
|
|
308
|
-
}
|
|
309
|
-
// Step 3: Get invitation module address
|
|
310
|
-
const invitationModuleAddress = await this.core.invitationFarm.invitationModule();
|
|
311
|
-
// Step 4: Referrals module address
|
|
312
|
-
const referralsModuleAddress = this.core.config.referralsModuleAddress;
|
|
313
|
-
// Step 5: Build the batch transaction
|
|
314
|
-
// - claimInvites write call (to actually claim the invites)
|
|
315
|
-
// - safeBatchTransferFrom to transfer invitation tokens to the invitation module
|
|
316
|
-
// Create the claimInvites write transaction
|
|
317
|
-
const claimInvitesWriteTx = this.core.invitationFarm.claimInvites(numberOfInvites);
|
|
318
|
-
// Step 6: Encode the createAccounts function call to the referrals module
|
|
319
|
-
// This call will be executed by the invitation module via the generic call proxy
|
|
320
|
-
const createAccountsCallData = encodeFunctionData({
|
|
321
|
-
abi: referralsModuleAbi,
|
|
322
|
-
functionName: 'createAccounts',
|
|
323
|
-
args: [signers],
|
|
324
|
-
});
|
|
325
|
-
// Step 7: Create safeBatchTransferFrom transaction to transfer invitation tokens to the invitation module
|
|
326
|
-
// - from: this avatar
|
|
327
|
-
// - to: invitation module
|
|
328
|
-
// - ids: the invitation IDs returned from claimInvites
|
|
329
|
-
// - amounts: all 96 CRC (96 * 10^18) per invitation
|
|
330
|
-
// - data: encoded as (address referralsModule, bytes callData) for the invitation module to execute
|
|
331
|
-
const amounts = [];
|
|
332
|
-
for (let i = 0; i < ids.length; i++) {
|
|
333
|
-
amounts.push(BigInt(96e18)); // 96 CRC in atto-circles
|
|
334
|
-
}
|
|
335
|
-
// Encode the data as (address, bytes) - referrals module address + createAccounts call data
|
|
336
|
-
const encodedData = encodeAbiParameters(parseAbiParameters('address, bytes'), [referralsModuleAddress, createAccountsCallData]);
|
|
337
|
-
const batchTransferTx = this.core.hubV2.safeBatchTransferFrom(this.address, invitationModuleAddress, ids, amounts, encodedData);
|
|
338
|
-
// Step 7: Execute the batch transaction
|
|
339
|
-
const receipt = await this.runner.sendTransaction([claimInvitesWriteTx, batchTransferTx]);
|
|
217
|
+
generateInvites: async (count) => {
|
|
218
|
+
const farm = new InviteFarm(this.core.config);
|
|
219
|
+
const result = await farm.generateInvites(this.address, count);
|
|
220
|
+
const receipt = await this.runner.sendTransaction(result.transactions);
|
|
340
221
|
return {
|
|
341
|
-
secrets,
|
|
342
|
-
signers,
|
|
222
|
+
secrets: result.invites.map((inv) => inv.secret),
|
|
223
|
+
signers: result.invites.map((inv) => inv.signer),
|
|
343
224
|
transactionReceipt: receipt,
|
|
344
225
|
};
|
|
345
226
|
},
|