@chipi-stack/backend 11.6.0 → 11.7.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.
@@ -0,0 +1,311 @@
1
+ 'use strict';
2
+
3
+ var types = require('@chipi-stack/types');
4
+ var shared = require('@chipi-stack/shared');
5
+ var starknet = require('starknet');
6
+ var CryptoES = require('crypto-es');
7
+ var crypto = require('crypto');
8
+
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var CryptoES__default = /*#__PURE__*/_interopDefault(CryptoES);
12
+
13
+ // src/sku-transactions.ts
14
+ var decryptPrivateKey = (encryptedPrivateKey, password) => {
15
+ try {
16
+ const bytes = CryptoES__default.default.AES.decrypt(encryptedPrivateKey, password);
17
+ const decrypted = bytes.toString(CryptoES__default.default.enc.Utf8);
18
+ if (!decrypted) throw new Error("Decryption failed");
19
+ return decrypted;
20
+ } catch (error) {
21
+ console.error("Decryption failed:", error);
22
+ throw new Error(`Decryption failed: ${error}`);
23
+ }
24
+ };
25
+
26
+ // src/execute-paymaster-transaction.ts
27
+ var executePaymasterTransaction = async ({
28
+ params,
29
+ bearerToken,
30
+ apiPublicKey,
31
+ backendUrl
32
+ }) => {
33
+ try {
34
+ const { encryptKey, wallet, calls } = params;
35
+ const privateKeyDecrypted = decryptPrivateKey(
36
+ wallet.encryptedPrivateKey,
37
+ encryptKey
38
+ );
39
+ if (!privateKeyDecrypted) {
40
+ throw new Error("Failed to decrypt private key");
41
+ }
42
+ const provider = new starknet.RpcProvider({
43
+ nodeUrl: "https://cloud.argent-api.com/v1/starknet/mainnet/rpc/v0.7"
44
+ });
45
+ const account = new starknet.Account(
46
+ provider,
47
+ wallet.publicKey,
48
+ privateKeyDecrypted
49
+ );
50
+ const typeDataResponse = await fetch(
51
+ `${backendUrl}/transactions/prepare-typed-data`,
52
+ {
53
+ method: "POST",
54
+ headers: {
55
+ "Content-Type": "application/json",
56
+ Authorization: `Bearer ${bearerToken}`,
57
+ "X-API-Key": apiPublicKey
58
+ },
59
+ body: JSON.stringify({
60
+ publicKey: wallet.publicKey,
61
+ calls,
62
+ accountClassHash: "0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f"
63
+ })
64
+ }
65
+ );
66
+ if (!typeDataResponse.ok) {
67
+ const errorText = await typeDataResponse.text();
68
+ throw new Error(`Error en la API: ${errorText}`);
69
+ }
70
+ const typeData = await typeDataResponse.json();
71
+ const userSignature = await account.signMessage(typeData);
72
+ const executeTransaction = await fetch(
73
+ `${backendUrl}/transactions/execute-sponsored-transaction`,
74
+ {
75
+ method: "POST",
76
+ headers: {
77
+ "Content-Type": "application/json",
78
+ Authorization: `Bearer ${bearerToken}`,
79
+ "X-API-Key": apiPublicKey
80
+ },
81
+ body: JSON.stringify({
82
+ publicKey: wallet.publicKey,
83
+ typeData,
84
+ userSignature: {
85
+ r: userSignature.r.toString(),
86
+ s: userSignature.s.toString(),
87
+ recovery: userSignature.recovery
88
+ }
89
+ })
90
+ }
91
+ );
92
+ if (!executeTransaction.ok) {
93
+ const errorText = await executeTransaction.text();
94
+ throw new Error(`Error en la API de ejecuci\xF3n: ${errorText}`);
95
+ }
96
+ const result = await executeTransaction.json();
97
+ if (!result.transactionHash) {
98
+ throw new Error("La respuesta no contiene el hash de la transacci\xF3n");
99
+ }
100
+ return result.transactionHash;
101
+ } catch (error) {
102
+ console.error("Error sending transaction with paymaster", error);
103
+ throw error;
104
+ }
105
+ };
106
+
107
+ // src/transactions.ts
108
+ var ChipiTransactions = class {
109
+ constructor(client) {
110
+ this.client = client;
111
+ }
112
+ /**
113
+ * Execute a gasless transaction using paymaster
114
+ */
115
+ async executeTransaction({
116
+ params,
117
+ bearerToken
118
+ }) {
119
+ return executePaymasterTransaction({
120
+ params,
121
+ bearerToken,
122
+ backendUrl: this.client.baseUrl,
123
+ apiPublicKey: this.client.getApiPublicKey()
124
+ });
125
+ }
126
+ /**
127
+ * Transfer tokens
128
+ */
129
+ async transfer({
130
+ params,
131
+ bearerToken
132
+ }) {
133
+ const { encryptKey, wallet, token, otherToken, recipient, amount } = params;
134
+ const contract = types.STARKNET_CONTRACTS[token];
135
+ let contractAddress = contract.contractAddress;
136
+ let decimals = contract.decimals;
137
+ if (token === "OTHER") {
138
+ if (!otherToken) {
139
+ throw new Error("Other token is required when token is OTHER");
140
+ }
141
+ contractAddress = otherToken.contractAddress;
142
+ decimals = otherToken.decimals;
143
+ }
144
+ const formattedAmount = shared.formatAmount(amount, decimals);
145
+ return this.executeTransaction({
146
+ params: {
147
+ encryptKey,
148
+ wallet,
149
+ calls: [
150
+ {
151
+ contractAddress,
152
+ entrypoint: "transfer",
153
+ calldata: [recipient, formattedAmount, "0x0"]
154
+ }
155
+ ]
156
+ },
157
+ bearerToken
158
+ });
159
+ }
160
+ /**
161
+ * Approve token spending
162
+ */
163
+ async approve(params) {
164
+ const formattedAmount = shared.formatAmount(params.amount, params.decimals);
165
+ return this.executeTransaction({
166
+ params: {
167
+ encryptKey: params.encryptKey,
168
+ wallet: params.wallet,
169
+ calls: [
170
+ {
171
+ contractAddress: params.contractAddress,
172
+ entrypoint: "approve",
173
+ calldata: [params.spender, formattedAmount, "0x0"]
174
+ }
175
+ ]
176
+ },
177
+ bearerToken: params.bearerToken
178
+ });
179
+ }
180
+ /**
181
+ * Call any contract method
182
+ */
183
+ // {
184
+ // encryptKey: string;
185
+ // wallet: any;
186
+ // calls: any[];
187
+ // bearerToken: string;
188
+ // }
189
+ async callAnyContract({
190
+ params,
191
+ bearerToken
192
+ }) {
193
+ return this.executeTransaction({
194
+ params,
195
+ bearerToken
196
+ });
197
+ }
198
+ /**
199
+ * Record a send transaction
200
+ */
201
+ async recordSendTransaction({
202
+ params,
203
+ bearerToken
204
+ }) {
205
+ const response = await this.client.post({
206
+ endpoint: `${shared.API_ENDPOINTS.TRANSACTIONS}/record-send`,
207
+ bearerToken,
208
+ body: params
209
+ });
210
+ return response;
211
+ }
212
+ };
213
+ var ChipiSkuTransactions = class {
214
+ constructor(client) {
215
+ this.client = client;
216
+ this.transactions = new ChipiTransactions(client);
217
+ }
218
+ /**
219
+ * Creates a SKU transaction with gasless execution
220
+ * @param params - Transaction parameters including amount, SKU ID, wallet, etc.
221
+ * @param bearerToken - Authentication token for API calls
222
+ * @returns Promise<SkuTransaction> - The created transaction record
223
+ */
224
+ async createSkuTransaction(params, bearerToken) {
225
+ const { mxnAmount, skuId, wallet, reference, externalUserId } = params;
226
+ this.client.baseUrl;
227
+ const usdAmount = await shared.getUsdAmount(mxnAmount, bearerToken, this.client);
228
+ const tokenAddress = types.STARKNET_CONTRACTS.USDC.contractAddress;
229
+ if (usdAmount <= 0) {
230
+ throw new Error(`Invalid USD amount: ${usdAmount}. Amount must be positive.`);
231
+ }
232
+ const minUsdAmount = Math.max(usdAmount, 1e-6);
233
+ const parsedAmount = shared.formatAmount(minUsdAmount.toString(), types.STARKNET_CONTRACTS.USDC.decimals);
234
+ const calls = [
235
+ {
236
+ contractAddress: tokenAddress,
237
+ entrypoint: "approve",
238
+ calldata: starknet.CallData.compile({
239
+ spender: shared.SKU_CONTRACTS.RECHARGER_WITH_STRK_MAINNET,
240
+ amount: starknet.cairo.uint256(parsedAmount)
241
+ })
242
+ },
243
+ {
244
+ contractAddress: shared.SKU_CONTRACTS.RECHARGER_WITH_STRK_MAINNET,
245
+ entrypoint: "newRecharge",
246
+ calldata: starknet.CallData.compile({
247
+ token_address: tokenAddress,
248
+ amount: starknet.cairo.uint256(parsedAmount),
249
+ rechargeId: crypto.createHash("sha256").update(crypto.randomUUID()).digest("hex").slice(0, 20),
250
+ productId: skuId,
251
+ carrierId: shared.CARRIER_IDS.CHIPI_PAY
252
+ })
253
+ },
254
+ {
255
+ contractAddress: shared.SKU_CONTRACTS.CHIPI_BILL_SERVICE,
256
+ entrypoint: "mint_item",
257
+ calldata: starknet.CallData.compile({
258
+ recipient: wallet.publicKey,
259
+ metadata: {
260
+ service_type: shared.SERVICE_TYPES.BUY_SERVICE,
261
+ timestamp: Date.now(),
262
+ chipi_user_id: starknet.hash.starknetKeccak(externalUserId || "0x0").toString(),
263
+ kyc: true,
264
+ amount: starknet.cairo.uint256(parsedAmount)
265
+ }
266
+ })
267
+ }
268
+ ];
269
+ const transactionHash = await this.transactions.executeTransaction({
270
+ params: {
271
+ encryptKey: params.encryptKey,
272
+ wallet,
273
+ calls
274
+ },
275
+ bearerToken
276
+ });
277
+ const input = {
278
+ walletAddress: wallet.publicKey,
279
+ skuId,
280
+ chain: shared.CHAIN_TYPES.STARKNET,
281
+ chainToken: shared.CHAIN_TOKEN_TYPES.USDC,
282
+ mxnAmount,
283
+ reference,
284
+ transactionHash,
285
+ usdAmount: minUsdAmount
286
+ };
287
+ const response = await this.client.post({
288
+ endpoint: `${shared.API_ENDPOINTS.SKU_TRANSACTIONS}`,
289
+ bearerToken,
290
+ body: input
291
+ });
292
+ return response;
293
+ }
294
+ /**
295
+ * Get a SKU transaction by transaction id
296
+ * @param id - The SKU transaction id
297
+ * @param bearerToken - Authentication token for API calls
298
+ * @returns Promise<SkuTransaction> - Single SKU transaction
299
+ */
300
+ async getSkuTransactionById(id, bearerToken) {
301
+ const response = await this.client.get({
302
+ endpoint: `${shared.API_ENDPOINTS.SKU_TRANSACTIONS}/${id}`,
303
+ bearerToken
304
+ });
305
+ return response;
306
+ }
307
+ };
308
+
309
+ exports.ChipiSkuTransactions = ChipiSkuTransactions;
310
+ //# sourceMappingURL=skuTransactions.js.map
311
+ //# sourceMappingURL=skuTransactions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/encryption.ts","../src/execute-paymaster-transaction.ts","../src/transactions.ts","../src/sku-transactions.ts"],"names":["CryptoES","RpcProvider","Account","STARKNET_CONTRACTS","formatAmount","API_ENDPOINTS","getUsdAmount","CallData","SKU_CONTRACTS","cairo","createHash","randomUUID","CARRIER_IDS","SERVICE_TYPES","hash","CHAIN_TYPES","CHAIN_TOKEN_TYPES"],"mappings":"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","file":"skuTransactions.js","sourcesContent":["import CryptoES from \"crypto-es\";\n\nexport const encryptPrivateKey = (\n privateKey: string,\n password: string\n): string => {\n return CryptoES.AES.encrypt(privateKey, password).toString();\n};\n\nexport const decryptPrivateKey = (\n encryptedPrivateKey: string,\n password: string\n): string => {\n try {\n const bytes = CryptoES.AES.decrypt(encryptedPrivateKey, password);\n const decrypted = bytes.toString(CryptoES.enc.Utf8);\n\n // Check if the decrypted string is empty\n if (!decrypted) throw new Error(\"Decryption failed\");\n\n return decrypted;\n } catch (error) {\n console.error(\"Decryption failed:\", error);\n throw new Error(`Decryption failed: ${error}`);\n }\n};\n","import type {\n ExecuteSponsoredTransactionResponse,\n ExecuteTransactionParams,\n} from \"@chipi-stack/types\";\nimport { Account, RpcProvider, TypedData } from \"starknet\";\nimport { decryptPrivateKey } from \"./encryption\";\n\n// This will need to be imported from the actual gasless SDK or implemented\n// For now, this is a placeholder implementation based on the original SDK\n\n/**\n * Execute a paymaster transaction (gasless)\n */\nexport const executePaymasterTransaction = async (\n {\n params,\n bearerToken,\n apiPublicKey,\n backendUrl,\n }: {\n params: ExecuteTransactionParams;\n bearerToken: string;\n apiPublicKey: string;\n backendUrl: string;\n }\n): Promise<string> => {\n // Backend url shit is temporary\n try {\n const { encryptKey, wallet, calls } = params;\n\n // Fetch the encrypted private key from clerk public metadata\n const privateKeyDecrypted = decryptPrivateKey(\n wallet.encryptedPrivateKey,\n encryptKey\n );\n\n if (!privateKeyDecrypted) {\n throw new Error(\"Failed to decrypt private key\");\n }\n\n const provider = new RpcProvider({\n nodeUrl: \"https://cloud.argent-api.com/v1/starknet/mainnet/rpc/v0.7\",\n });\n\n const account = new Account(\n provider,\n wallet.publicKey,\n privateKeyDecrypted\n );\n\n // Build the type data\n const typeDataResponse = await fetch(\n `${backendUrl}/transactions/prepare-typed-data`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${bearerToken}`,\n \"X-API-Key\": apiPublicKey,\n },\n body: JSON.stringify({\n publicKey: wallet.publicKey,\n calls: calls,\n accountClassHash:\n \"0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f\",\n }),\n }\n );\n\n if (!typeDataResponse.ok) {\n const errorText = await typeDataResponse.text();\n throw new Error(`Error en la API: ${errorText}`);\n }\n\n const typeData = (await typeDataResponse.json()) as TypedData;\n\n // Sign the message\n const userSignature = await account.signMessage(typeData);\n\n // Execute the transaction\n const executeTransaction = await fetch(\n `${backendUrl}/transactions/execute-sponsored-transaction`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${bearerToken}`,\n \"X-API-Key\": apiPublicKey,\n },\n body: JSON.stringify({\n publicKey: wallet.publicKey,\n typeData: typeData,\n userSignature: {\n r: (userSignature as any).r.toString(),\n s: (userSignature as any).s.toString(),\n recovery: (userSignature as any).recovery,\n },\n }),\n }\n );\n\n if (!executeTransaction.ok) {\n const errorText = await executeTransaction.text();\n throw new Error(`Error en la API de ejecución: ${errorText}`);\n }\n\n const result =\n (await executeTransaction.json()) as ExecuteSponsoredTransactionResponse;\n\n if (!result.transactionHash) {\n throw new Error(\"La respuesta no contiene el hash de la transacción\");\n }\n\n return result.transactionHash;\n } catch (error) {\n console.error(\"Error sending transaction with paymaster\", error);\n throw error;\n }\n};\n","import {\n CallAnyContractParams,\n STARKNET_CONTRACTS,\n type ExecuteTransactionParams,\n type RecordSendTransactionParams,\n type Transaction,\n type TransferParams,\n} from \"@chipi-stack/types\";\nimport { API_ENDPOINTS, formatAmount } from \"@chipi-stack/shared\";\nimport { ChipiClient } from \"./client\";\nimport { executePaymasterTransaction } from \"./execute-paymaster-transaction\";\n\n/**\n * Transaction management utilities\n */\nexport class ChipiTransactions {\n constructor(private client: ChipiClient) {}\n /**\n * Execute a gasless transaction using paymaster\n */\n async executeTransaction({\n params,\n bearerToken,\n }: {\n params: ExecuteTransactionParams;\n bearerToken: string;\n }): Promise<string> {\n return executePaymasterTransaction({\n params,\n bearerToken,\n backendUrl: this.client.baseUrl,\n apiPublicKey: this.client.getApiPublicKey(),\n });\n }\n\n /**\n * Transfer tokens\n */\n async transfer({\n params,\n bearerToken,\n }: {\n params: TransferParams;\n bearerToken: string;\n }): Promise<string> {\n const { encryptKey, wallet, token, otherToken, recipient, amount } = params;\n const contract = STARKNET_CONTRACTS[token];\n let contractAddress = contract.contractAddress;\n let decimals = contract.decimals;\n if (token === \"OTHER\") {\n if (!otherToken) {\n throw new Error(\"Other token is required when token is OTHER\");\n }\n contractAddress = otherToken.contractAddress;\n decimals = otherToken.decimals;\n }\n const formattedAmount = formatAmount(amount, decimals);\n return this.executeTransaction({\n params: {\n encryptKey,\n wallet,\n calls: [\n {\n contractAddress,\n entrypoint: \"transfer\",\n calldata: [recipient, formattedAmount, \"0x0\"],\n },\n ],\n },\n bearerToken,\n });\n }\n\n /**\n * Approve token spending\n */\n async approve(params: {\n encryptKey: string;\n wallet: any;\n contractAddress: string;\n spender: string;\n amount: string | number;\n decimals?: number;\n bearerToken: string;\n }): Promise<string> {\n const formattedAmount = formatAmount(params.amount, params.decimals);\n\n return this.executeTransaction({\n params: {\n encryptKey: params.encryptKey,\n wallet: params.wallet,\n calls: [\n {\n contractAddress: params.contractAddress,\n entrypoint: \"approve\",\n calldata: [params.spender, formattedAmount, \"0x0\"],\n },\n ],\n },\n bearerToken: params.bearerToken,\n });\n }\n\n /**\n * Call any contract method\n */\n // {\n // encryptKey: string;\n // wallet: any;\n // calls: any[];\n // bearerToken: string;\n // }\n\n async callAnyContract({\n params,\n bearerToken,\n }: {\n params: CallAnyContractParams;\n bearerToken: string;\n }): Promise<string> {\n return this.executeTransaction({\n params,\n bearerToken,\n });\n }\n\n /**\n * Record a send transaction\n */\n async recordSendTransaction({\n params,\n bearerToken,\n }: {\n params: RecordSendTransactionParams;\n bearerToken: string;\n }): Promise<Transaction> {\n const response = await this.client.post<Transaction>({\n endpoint: `${API_ENDPOINTS.TRANSACTIONS}/record-send`,\n bearerToken,\n body: params,\n });\n return response;\n }\n}\n","import { CreateSkuTransactionParams, Sku, SkuTransaction, STARKNET_CONTRACTS } from \"@chipi-stack/types\";\nimport { ChipiClient } from \"./client\";\nimport { ChipiTransactions } from \"./transactions\";\n\nimport { CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, SERVICE_TYPES, SKU_CONTRACTS, formatAmount, getUsdAmount } from \"@chipi-stack/shared\";\nimport { Call, CallData, cairo, hash } from \"starknet\";\nimport { API_ENDPOINTS } from \"@chipi-stack/shared\";\nimport { createHash, randomUUID } from \"crypto\";\n\n\nexport class ChipiSkuTransactions {\n private transactions: ChipiTransactions;\n\n constructor(private client: ChipiClient) {\n this.transactions = new ChipiTransactions(client);\n }\n\n\n /**\n * Creates a SKU transaction with gasless execution\n * @param params - Transaction parameters including amount, SKU ID, wallet, etc.\n * @param bearerToken - Authentication token for API calls\n * @returns Promise<SkuTransaction> - The created transaction record\n */\n async createSkuTransaction(params: CreateSkuTransactionParams, bearerToken: string): Promise<SkuTransaction> {\n\n\n const { mxnAmount, skuId, wallet, reference, externalUserId } = params;\n const backendUrl = this.client.baseUrl;\n const usdAmount = await getUsdAmount(mxnAmount, bearerToken, this.client);\n const tokenAddress = STARKNET_CONTRACTS.USDC.contractAddress as `0x${string}`;\n if (usdAmount <= 0) {\n throw new Error(`Invalid USD amount: ${usdAmount}. Amount must be positive.`);\n }\n const minUsdAmount = Math.max(usdAmount, 0.000001);\n const parsedAmount = formatAmount(minUsdAmount.toString(), STARKNET_CONTRACTS.USDC.decimals);\n const calls: Call[] = [\n {\n contractAddress: tokenAddress,\n entrypoint: \"approve\",\n calldata: CallData.compile({\n spender: SKU_CONTRACTS.RECHARGER_WITH_STRK_MAINNET,\n amount: cairo.uint256(parsedAmount),\n }),\n },\n {\n contractAddress: SKU_CONTRACTS.RECHARGER_WITH_STRK_MAINNET,\n entrypoint: \"newRecharge\",\n calldata: CallData.compile({\n token_address: tokenAddress,\n amount: cairo.uint256(parsedAmount),\n rechargeId: createHash('sha256').update(randomUUID()).digest('hex').slice(0, 20),\n productId: skuId,\n carrierId: CARRIER_IDS.CHIPI_PAY,\n }),\n },\n {\n contractAddress: SKU_CONTRACTS.CHIPI_BILL_SERVICE,\n entrypoint: \"mint_item\",\n calldata: CallData.compile({\n recipient: wallet.publicKey,\n metadata: {\n service_type: SERVICE_TYPES.BUY_SERVICE,\n timestamp: Date.now(),\n chipi_user_id: hash.starknetKeccak(externalUserId || \"0x0\").toString(),\n kyc: true,\n amount: cairo.uint256(parsedAmount),\n },\n }),\n },\n ];\n\n const transactionHash = await this.transactions.executeTransaction({\n params: {\n encryptKey: params.encryptKey,\n wallet: wallet,\n calls: calls,\n },\n bearerToken: bearerToken,\n });\n\n const input = {\n walletAddress: wallet.publicKey,\n skuId: skuId,\n chain: CHAIN_TYPES.STARKNET,\n chainToken: CHAIN_TOKEN_TYPES.USDC,\n mxnAmount: mxnAmount,\n reference: reference,\n transactionHash: transactionHash,\n usdAmount: minUsdAmount,\n }\n // Record the transaction and fetch the purchase of the service \n const response = await this.client.post<SkuTransaction>({\n endpoint: `${API_ENDPOINTS.SKU_TRANSACTIONS}`,\n bearerToken,\n body: input,\n });\n\n return response;\n }\n\n\n\n /**\n * Get a SKU transaction by transaction id\n * @param id - The SKU transaction id\n * @param bearerToken - Authentication token for API calls\n * @returns Promise<SkuTransaction> - Single SKU transaction\n */\n async getSkuTransactionById(\n id: string,\n bearerToken: string,\n ): Promise<SkuTransaction> {\n const response = await this.client.get<SkuTransaction>({\n endpoint: `${API_ENDPOINTS.SKU_TRANSACTIONS}/${id}`,\n bearerToken,\n });\n return response;\n }\n}\n"]}
@@ -0,0 +1,305 @@
1
+ import { STARKNET_CONTRACTS } from '@chipi-stack/types';
2
+ import { getUsdAmount, formatAmount, SKU_CONTRACTS, CARRIER_IDS, SERVICE_TYPES, CHAIN_TOKEN_TYPES, CHAIN_TYPES, API_ENDPOINTS } from '@chipi-stack/shared';
3
+ import { CallData, cairo, hash, RpcProvider, Account } from 'starknet';
4
+ import CryptoES from 'crypto-es';
5
+ import { createHash, randomUUID } from 'crypto';
6
+
7
+ // src/sku-transactions.ts
8
+ var decryptPrivateKey = (encryptedPrivateKey, password) => {
9
+ try {
10
+ const bytes = CryptoES.AES.decrypt(encryptedPrivateKey, password);
11
+ const decrypted = bytes.toString(CryptoES.enc.Utf8);
12
+ if (!decrypted) throw new Error("Decryption failed");
13
+ return decrypted;
14
+ } catch (error) {
15
+ console.error("Decryption failed:", error);
16
+ throw new Error(`Decryption failed: ${error}`);
17
+ }
18
+ };
19
+
20
+ // src/execute-paymaster-transaction.ts
21
+ var executePaymasterTransaction = async ({
22
+ params,
23
+ bearerToken,
24
+ apiPublicKey,
25
+ backendUrl
26
+ }) => {
27
+ try {
28
+ const { encryptKey, wallet, calls } = params;
29
+ const privateKeyDecrypted = decryptPrivateKey(
30
+ wallet.encryptedPrivateKey,
31
+ encryptKey
32
+ );
33
+ if (!privateKeyDecrypted) {
34
+ throw new Error("Failed to decrypt private key");
35
+ }
36
+ const provider = new RpcProvider({
37
+ nodeUrl: "https://cloud.argent-api.com/v1/starknet/mainnet/rpc/v0.7"
38
+ });
39
+ const account = new Account(
40
+ provider,
41
+ wallet.publicKey,
42
+ privateKeyDecrypted
43
+ );
44
+ const typeDataResponse = await fetch(
45
+ `${backendUrl}/transactions/prepare-typed-data`,
46
+ {
47
+ method: "POST",
48
+ headers: {
49
+ "Content-Type": "application/json",
50
+ Authorization: `Bearer ${bearerToken}`,
51
+ "X-API-Key": apiPublicKey
52
+ },
53
+ body: JSON.stringify({
54
+ publicKey: wallet.publicKey,
55
+ calls,
56
+ accountClassHash: "0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f"
57
+ })
58
+ }
59
+ );
60
+ if (!typeDataResponse.ok) {
61
+ const errorText = await typeDataResponse.text();
62
+ throw new Error(`Error en la API: ${errorText}`);
63
+ }
64
+ const typeData = await typeDataResponse.json();
65
+ const userSignature = await account.signMessage(typeData);
66
+ const executeTransaction = await fetch(
67
+ `${backendUrl}/transactions/execute-sponsored-transaction`,
68
+ {
69
+ method: "POST",
70
+ headers: {
71
+ "Content-Type": "application/json",
72
+ Authorization: `Bearer ${bearerToken}`,
73
+ "X-API-Key": apiPublicKey
74
+ },
75
+ body: JSON.stringify({
76
+ publicKey: wallet.publicKey,
77
+ typeData,
78
+ userSignature: {
79
+ r: userSignature.r.toString(),
80
+ s: userSignature.s.toString(),
81
+ recovery: userSignature.recovery
82
+ }
83
+ })
84
+ }
85
+ );
86
+ if (!executeTransaction.ok) {
87
+ const errorText = await executeTransaction.text();
88
+ throw new Error(`Error en la API de ejecuci\xF3n: ${errorText}`);
89
+ }
90
+ const result = await executeTransaction.json();
91
+ if (!result.transactionHash) {
92
+ throw new Error("La respuesta no contiene el hash de la transacci\xF3n");
93
+ }
94
+ return result.transactionHash;
95
+ } catch (error) {
96
+ console.error("Error sending transaction with paymaster", error);
97
+ throw error;
98
+ }
99
+ };
100
+
101
+ // src/transactions.ts
102
+ var ChipiTransactions = class {
103
+ constructor(client) {
104
+ this.client = client;
105
+ }
106
+ /**
107
+ * Execute a gasless transaction using paymaster
108
+ */
109
+ async executeTransaction({
110
+ params,
111
+ bearerToken
112
+ }) {
113
+ return executePaymasterTransaction({
114
+ params,
115
+ bearerToken,
116
+ backendUrl: this.client.baseUrl,
117
+ apiPublicKey: this.client.getApiPublicKey()
118
+ });
119
+ }
120
+ /**
121
+ * Transfer tokens
122
+ */
123
+ async transfer({
124
+ params,
125
+ bearerToken
126
+ }) {
127
+ const { encryptKey, wallet, token, otherToken, recipient, amount } = params;
128
+ const contract = STARKNET_CONTRACTS[token];
129
+ let contractAddress = contract.contractAddress;
130
+ let decimals = contract.decimals;
131
+ if (token === "OTHER") {
132
+ if (!otherToken) {
133
+ throw new Error("Other token is required when token is OTHER");
134
+ }
135
+ contractAddress = otherToken.contractAddress;
136
+ decimals = otherToken.decimals;
137
+ }
138
+ const formattedAmount = formatAmount(amount, decimals);
139
+ return this.executeTransaction({
140
+ params: {
141
+ encryptKey,
142
+ wallet,
143
+ calls: [
144
+ {
145
+ contractAddress,
146
+ entrypoint: "transfer",
147
+ calldata: [recipient, formattedAmount, "0x0"]
148
+ }
149
+ ]
150
+ },
151
+ bearerToken
152
+ });
153
+ }
154
+ /**
155
+ * Approve token spending
156
+ */
157
+ async approve(params) {
158
+ const formattedAmount = formatAmount(params.amount, params.decimals);
159
+ return this.executeTransaction({
160
+ params: {
161
+ encryptKey: params.encryptKey,
162
+ wallet: params.wallet,
163
+ calls: [
164
+ {
165
+ contractAddress: params.contractAddress,
166
+ entrypoint: "approve",
167
+ calldata: [params.spender, formattedAmount, "0x0"]
168
+ }
169
+ ]
170
+ },
171
+ bearerToken: params.bearerToken
172
+ });
173
+ }
174
+ /**
175
+ * Call any contract method
176
+ */
177
+ // {
178
+ // encryptKey: string;
179
+ // wallet: any;
180
+ // calls: any[];
181
+ // bearerToken: string;
182
+ // }
183
+ async callAnyContract({
184
+ params,
185
+ bearerToken
186
+ }) {
187
+ return this.executeTransaction({
188
+ params,
189
+ bearerToken
190
+ });
191
+ }
192
+ /**
193
+ * Record a send transaction
194
+ */
195
+ async recordSendTransaction({
196
+ params,
197
+ bearerToken
198
+ }) {
199
+ const response = await this.client.post({
200
+ endpoint: `${API_ENDPOINTS.TRANSACTIONS}/record-send`,
201
+ bearerToken,
202
+ body: params
203
+ });
204
+ return response;
205
+ }
206
+ };
207
+ var ChipiSkuTransactions = class {
208
+ constructor(client) {
209
+ this.client = client;
210
+ this.transactions = new ChipiTransactions(client);
211
+ }
212
+ /**
213
+ * Creates a SKU transaction with gasless execution
214
+ * @param params - Transaction parameters including amount, SKU ID, wallet, etc.
215
+ * @param bearerToken - Authentication token for API calls
216
+ * @returns Promise<SkuTransaction> - The created transaction record
217
+ */
218
+ async createSkuTransaction(params, bearerToken) {
219
+ const { mxnAmount, skuId, wallet, reference, externalUserId } = params;
220
+ this.client.baseUrl;
221
+ const usdAmount = await getUsdAmount(mxnAmount, bearerToken, this.client);
222
+ const tokenAddress = STARKNET_CONTRACTS.USDC.contractAddress;
223
+ if (usdAmount <= 0) {
224
+ throw new Error(`Invalid USD amount: ${usdAmount}. Amount must be positive.`);
225
+ }
226
+ const minUsdAmount = Math.max(usdAmount, 1e-6);
227
+ const parsedAmount = formatAmount(minUsdAmount.toString(), STARKNET_CONTRACTS.USDC.decimals);
228
+ const calls = [
229
+ {
230
+ contractAddress: tokenAddress,
231
+ entrypoint: "approve",
232
+ calldata: CallData.compile({
233
+ spender: SKU_CONTRACTS.RECHARGER_WITH_STRK_MAINNET,
234
+ amount: cairo.uint256(parsedAmount)
235
+ })
236
+ },
237
+ {
238
+ contractAddress: SKU_CONTRACTS.RECHARGER_WITH_STRK_MAINNET,
239
+ entrypoint: "newRecharge",
240
+ calldata: CallData.compile({
241
+ token_address: tokenAddress,
242
+ amount: cairo.uint256(parsedAmount),
243
+ rechargeId: createHash("sha256").update(randomUUID()).digest("hex").slice(0, 20),
244
+ productId: skuId,
245
+ carrierId: CARRIER_IDS.CHIPI_PAY
246
+ })
247
+ },
248
+ {
249
+ contractAddress: SKU_CONTRACTS.CHIPI_BILL_SERVICE,
250
+ entrypoint: "mint_item",
251
+ calldata: CallData.compile({
252
+ recipient: wallet.publicKey,
253
+ metadata: {
254
+ service_type: SERVICE_TYPES.BUY_SERVICE,
255
+ timestamp: Date.now(),
256
+ chipi_user_id: hash.starknetKeccak(externalUserId || "0x0").toString(),
257
+ kyc: true,
258
+ amount: cairo.uint256(parsedAmount)
259
+ }
260
+ })
261
+ }
262
+ ];
263
+ const transactionHash = await this.transactions.executeTransaction({
264
+ params: {
265
+ encryptKey: params.encryptKey,
266
+ wallet,
267
+ calls
268
+ },
269
+ bearerToken
270
+ });
271
+ const input = {
272
+ walletAddress: wallet.publicKey,
273
+ skuId,
274
+ chain: CHAIN_TYPES.STARKNET,
275
+ chainToken: CHAIN_TOKEN_TYPES.USDC,
276
+ mxnAmount,
277
+ reference,
278
+ transactionHash,
279
+ usdAmount: minUsdAmount
280
+ };
281
+ const response = await this.client.post({
282
+ endpoint: `${API_ENDPOINTS.SKU_TRANSACTIONS}`,
283
+ bearerToken,
284
+ body: input
285
+ });
286
+ return response;
287
+ }
288
+ /**
289
+ * Get a SKU transaction by transaction id
290
+ * @param id - The SKU transaction id
291
+ * @param bearerToken - Authentication token for API calls
292
+ * @returns Promise<SkuTransaction> - Single SKU transaction
293
+ */
294
+ async getSkuTransactionById(id, bearerToken) {
295
+ const response = await this.client.get({
296
+ endpoint: `${API_ENDPOINTS.SKU_TRANSACTIONS}/${id}`,
297
+ bearerToken
298
+ });
299
+ return response;
300
+ }
301
+ };
302
+
303
+ export { ChipiSkuTransactions };
304
+ //# sourceMappingURL=skuTransactions.mjs.map
305
+ //# sourceMappingURL=skuTransactions.mjs.map