@zebec-network/solana-payroll-sdk 2.5.0 → 2.6.0-dev.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.
@@ -2,3 +2,5 @@ import type { RpcNetwork } from "./types.js";
2
2
  export declare const PAYROLL_NAME_BUFFER_SIZE = 128;
3
3
  export declare const PAYROLL_PROGRAM_ID: Record<RpcNetwork, string>;
4
4
  export declare const USX_DECIMALS = 6;
5
+ export declare const DEFAULT_FEE_RATE_IN_BPS = 500;
6
+ export declare const BPS_DENOMINATOR = 10000;
package/dist/constants.js CHANGED
@@ -4,3 +4,5 @@ export const PAYROLL_PROGRAM_ID = {
4
4
  devnet: "zPAY457TttFCcaCoA3imYyEHc2sPvLMTQgVxjAfodSM",
5
5
  };
6
6
  export const USX_DECIMALS = 6;
7
+ export const DEFAULT_FEE_RATE_IN_BPS = 500;
8
+ export const BPS_DENOMINATOR = 10000;
@@ -156,3 +156,45 @@ export declare function createDistributeRewardsInstruction(program: Program<Zebe
156
156
  }[];
157
157
  checkId: number[];
158
158
  }, remainingAccounts: AccountMeta[]): Promise<TransactionInstruction>;
159
+ export declare function createCreateCardInstruction(payrollProgram: Program<ZebecPayrollIdl>, accounts: {
160
+ cardPurchasePda: PublicKey;
161
+ cardVault: PublicKey;
162
+ cardVaultAta: PublicKey;
163
+ enterpriseCardConfig: PublicKey;
164
+ enterpriseCardIndex: PublicKey;
165
+ feePayer: PublicKey;
166
+ revenueVault: PublicKey;
167
+ revenueVaultAta: PublicKey;
168
+ usdcMint: PublicKey;
169
+ user: PublicKey;
170
+ userAta: PublicKey;
171
+ userPurchaseRecordPda: PublicKey;
172
+ }, data: {
173
+ amount: BN;
174
+ currency: string;
175
+ emailHash: number[];
176
+ index: BN;
177
+ reloadCardId: string;
178
+ }): Promise<TransactionInstruction>;
179
+ export declare function createSwapAndCreateCardInstruction(payrollProgram: Program<ZebecPayrollIdl>, accounts: {
180
+ cardPurchasePda: PublicKey;
181
+ cardVault: PublicKey;
182
+ cardVaultAta: PublicKey;
183
+ enterpriseCardConfig: PublicKey;
184
+ enterpriseCardIndex: PublicKey;
185
+ feePayer: PublicKey;
186
+ jupiterProgram: PublicKey;
187
+ revenueVault: PublicKey;
188
+ revenueVaultAta: PublicKey;
189
+ sourceToken: PublicKey;
190
+ usdcMint: PublicKey;
191
+ user: PublicKey;
192
+ userAta: PublicKey;
193
+ userPurchaseRecordPda: PublicKey;
194
+ }, data: {
195
+ currency: string;
196
+ emailHash: number[];
197
+ index: BN;
198
+ reloadCardId: string;
199
+ swapData: Buffer;
200
+ }, remainingAccounts: AccountMeta[]): Promise<TransactionInstruction>;
@@ -195,3 +195,55 @@ export async function createDistributeRewardsInstruction(program, accounts, data
195
195
  .remainingAccounts(remainingAccounts)
196
196
  .instruction();
197
197
  }
198
+ export async function createCreateCardInstruction(payrollProgram, accounts, data) {
199
+ return payrollProgram.methods
200
+ .enterpriseCreateCard({
201
+ amount: data.amount,
202
+ currency: data.currency,
203
+ emailHash: data.emailHash,
204
+ index: data.index,
205
+ reloadCardId: data.reloadCardId,
206
+ })
207
+ .accountsPartial({
208
+ cardPurchasePda: accounts.cardPurchasePda,
209
+ cardVault: accounts.cardVault,
210
+ cardVaultAta: accounts.cardVaultAta,
211
+ enterpriseCardConfig: accounts.enterpriseCardConfig,
212
+ enterpriseCardIndex: accounts.enterpriseCardIndex,
213
+ feePayer: accounts.feePayer,
214
+ revenueVault: accounts.revenueVault,
215
+ revenueVaultAta: accounts.revenueVaultAta,
216
+ usdcMint: accounts.usdcMint,
217
+ user: accounts.user,
218
+ userAta: accounts.userAta,
219
+ userPurchaseRecordPda: accounts.userPurchaseRecordPda,
220
+ })
221
+ .instruction();
222
+ }
223
+ export async function createSwapAndCreateCardInstruction(payrollProgram, accounts, data, remainingAccounts) {
224
+ return payrollProgram.methods
225
+ .swapAndCreateCard({
226
+ currency: data.currency,
227
+ emailHash: data.emailHash,
228
+ index: data.index,
229
+ reloadCardId: data.reloadCardId,
230
+ swapData: data.swapData,
231
+ })
232
+ .accountsPartial({
233
+ cardPurchasePda: accounts.cardPurchasePda,
234
+ cardVault: accounts.cardVault,
235
+ cardVaultAta: accounts.cardVaultAta,
236
+ enterpriseCardConfig: accounts.enterpriseCardConfig,
237
+ enterpriseCardIndex: accounts.enterpriseCardIndex,
238
+ feePayer: accounts.feePayer,
239
+ revenueVault: accounts.revenueVault,
240
+ revenueVaultAta: accounts.revenueVaultAta,
241
+ sourceToken: accounts.sourceToken,
242
+ usdcMint: accounts.usdcMint,
243
+ user: accounts.user,
244
+ userAta: accounts.userAta,
245
+ userPurchaseRecordPda: accounts.userPurchaseRecordPda,
246
+ })
247
+ .remainingAccounts(remainingAccounts)
248
+ .instruction();
249
+ }
package/dist/pda.d.ts CHANGED
@@ -6,3 +6,7 @@ export declare function deriveYieldConfigPda(configProgramId: Address): [PublicK
6
6
  export declare function deriveCompanyDepositPda(companyId: Buffer, nonce: bigint, payrollProgramId: Address): [PublicKey, number];
7
7
  export declare function deriveCompanyNoncePda(companyId: Buffer, payrollProgramId: Address): [PublicKey, number];
8
8
  export declare function deriveCheckAccountPda(checkId: Buffer | Uint8Array, payrollProgramId: Address): [PublicKey, number];
9
+ export declare function deriveEnterpriseCardIndexPda(entCardConfigName: string, payrollProgramId: Address): [PublicKey, number];
10
+ export declare function deriveEnterpriseCardPurchasePda(userAddress: Address, entCardConfigName: string, cardIndex: bigint, payrollProgramId: Address): [PublicKey, number];
11
+ export declare function deriveEnterpriseUserPurchaseRecordPda(userAddress: Address, entCardConfigName: string, payrollProgramId: Address): [PublicKey, number];
12
+ export declare function deriveEnterpriseCardConfigPda(entCardConfigName: string, zebecConfigProgramId: Address): [PublicKey, number];
package/dist/pda.js CHANGED
@@ -4,9 +4,13 @@ import BN from "bn.js";
4
4
  const ZEBEC_CONFIG_PROGRAM_SEEDS = {
5
5
  PAYROLL_CONFIG: utils.bytes.utf8.encode("payroll_config"),
6
6
  YIELD_CONFIG: utils.bytes.utf8.encode("yield_config"),
7
+ ENTERPRISE_CARD_CONFIG: utils.bytes.utf8.encode("enterprise_card_config"),
7
8
  };
8
9
  const PAYROLL_PROGRAM_SEEDS = {
9
- COMPANY_DEPOSIT: utils.bytes.utf8.encode("Yield"),
10
+ YIELD_COMPANY_DEPOSIT: utils.bytes.utf8.encode("Yield"),
11
+ ENT_USER_PURCHASE_RECORD: utils.bytes.utf8.encode("UserPurchaseRecord"),
12
+ ENT_USER_CARD_PURCHASE: utils.bytes.utf8.encode("CardPurchase"),
13
+ ENT_CARD_INDEX: utils.bytes.utf8.encode("EnterpriseCardIndex"),
10
14
  };
11
15
  export function derivePayrollConfigPda(configName, configProgramId) {
12
16
  return PublicKey.findProgramAddressSync([
@@ -24,7 +28,7 @@ export function deriveCompanyDepositPda(companyId, nonce, payrollProgramId) {
24
28
  return PublicKey.findProgramAddressSync([
25
29
  companyId,
26
30
  new BN(nonce).toArrayLike(Buffer, "le", 8),
27
- PAYROLL_PROGRAM_SEEDS.COMPANY_DEPOSIT,
31
+ PAYROLL_PROGRAM_SEEDS.YIELD_COMPANY_DEPOSIT,
28
32
  ], translateAddress(payrollProgramId));
29
33
  }
30
34
  export function deriveCompanyNoncePda(companyId, payrollProgramId) {
@@ -33,3 +37,30 @@ export function deriveCompanyNoncePda(companyId, payrollProgramId) {
33
37
  export function deriveCheckAccountPda(checkId, payrollProgramId) {
34
38
  return PublicKey.findProgramAddressSync([checkId], translateAddress(payrollProgramId));
35
39
  }
40
+ export function deriveEnterpriseCardIndexPda(entCardConfigName, payrollProgramId) {
41
+ return PublicKey.findProgramAddressSync([
42
+ PAYROLL_PROGRAM_SEEDS.ENT_CARD_INDEX,
43
+ utils.bytes.utf8.encode(entCardConfigName),
44
+ ], translateAddress(payrollProgramId));
45
+ }
46
+ export function deriveEnterpriseCardPurchasePda(userAddress, entCardConfigName, cardIndex, payrollProgramId) {
47
+ return PublicKey.findProgramAddressSync([
48
+ PAYROLL_PROGRAM_SEEDS.ENT_USER_CARD_PURCHASE,
49
+ translateAddress(userAddress).toBuffer(),
50
+ utils.bytes.utf8.encode(entCardConfigName),
51
+ new BN(cardIndex).toArrayLike(Buffer, "le"),
52
+ ], translateAddress(payrollProgramId));
53
+ }
54
+ export function deriveEnterpriseUserPurchaseRecordPda(userAddress, entCardConfigName, payrollProgramId) {
55
+ return PublicKey.findProgramAddressSync([
56
+ PAYROLL_PROGRAM_SEEDS.ENT_USER_PURCHASE_RECORD,
57
+ translateAddress(userAddress).toBuffer(),
58
+ utils.bytes.utf8.encode(entCardConfigName),
59
+ ], translateAddress(payrollProgramId));
60
+ }
61
+ export function deriveEnterpriseCardConfigPda(entCardConfigName, zebecConfigProgramId) {
62
+ return PublicKey.findProgramAddressSync([
63
+ ZEBEC_CONFIG_PROGRAM_SEEDS.ENTERPRISE_CARD_CONFIG,
64
+ utils.bytes.utf8.encode(entCardConfigName),
65
+ ], translateAddress(zebecConfigProgramId));
66
+ }
@@ -3,12 +3,12 @@ import { type Commitment } from "@solana/web3.js";
3
3
  import { MultiTransactionPayload, TransactionPayload } from "@zebec-network/solana-common";
4
4
  import type { ZebecConfigs as ZebecConfigsIdl } from "@zebec-network/zebec_configs";
5
5
  import type { ZebecPayroll as ZebecPayrollIdl } from "@zebec-network/zebec_payroll";
6
- import type { CancelMultiplePayrollParams, CancelPayrollParams, CancelUnlockParams, ChangePayrollReceiverParams, CompanyDepositInfo, CompanyNonceInfo, CompleteUnlockParams, CreateMultiplePayrollParams, CreatePayrollParams, DistributeRewardsParams, PauseResumeMultiplePayrollParams, PauseResumePayrollParams, PayrollConfigInfo, PayrollMetadataInfo, RequestUnlockParams, SetMultipleTopupDelegateParams, SetTopupDelegateParams, TokenMetadata, TopupMultiplePayrollParams, TopupPayrollParams, WithdrawMultiplePayrollParams, WithdrawPayrollParams, YieldDepositParams } from "./types.js";
6
+ import type { CancelMultiplePayrollParams, CancelPayrollParams, CancelUnlockParams, ChangePayrollReceiverParams, CompanyDepositInfo, CompanyNonceInfo, CompleteUnlockParams, CreateMultiplePayrollParams, CreatePayrollParams, DistributeRewardsParams, Numeric, PauseResumeMultiplePayrollParams, PauseResumePayrollParams, PayrollConfigInfo, PayrollMetadataInfo, RequestUnlockParams, SetMultipleTopupDelegateParams, SetTopupDelegateParams, TokenMetadata, TopupMultiplePayrollParams, TopupPayrollParams, WithdrawMultiplePayrollParams, WithdrawPayrollParams, YieldDepositParams } from "./types.js";
7
7
  export declare function getPayrollConfig(configProgram: Program<ZebecConfigsIdl>, configName: string): Promise<PayrollConfigInfo>;
8
8
  export declare function getWhitelistedTokens(configProgram: Program<ZebecConfigsIdl>, configName: string, commitment?: "processed" | "confirmed" | "finalized"): Promise<TokenMetadata[]>;
9
9
  export declare function getPayrollMetadataInfo(program: Program<ZebecPayrollIdl>, payrollMetadata: Address, commitment?: Commitment): Promise<PayrollMetadataInfo>;
10
- export declare function createPayroll(payrollProgram: Program<ZebecPayrollIdl>, configProgram: Program<ZebecConfigsIdl>, params: CreatePayrollParams, payrollFeeBaseUrl: string): Promise<TransactionPayload>;
11
- export declare function createMultiplePayroll(payrollProgram: Program<ZebecPayrollIdl>, configProgram: Program<ZebecConfigsIdl>, params: CreateMultiplePayrollParams, payrollFeeBaseUrl: string): Promise<MultiTransactionPayload>;
10
+ export declare function createPayroll(payrollProgram: Program<ZebecPayrollIdl>, configProgram: Program<ZebecConfigsIdl>, params: CreatePayrollParams, _payrollFeeBaseUrl: string): Promise<TransactionPayload>;
11
+ export declare function createMultiplePayroll(payrollProgram: Program<ZebecPayrollIdl>, configProgram: Program<ZebecConfigsIdl>, params: CreateMultiplePayrollParams, _payrollFeeBaseUrl: string): Promise<MultiTransactionPayload>;
12
12
  export declare function cancelPayroll(program: Program<ZebecPayrollIdl>, params: CancelPayrollParams): Promise<TransactionPayload>;
13
13
  export declare function cancelMultiplePayroll(program: Program<ZebecPayrollIdl>, params: CancelMultiplePayrollParams): Promise<MultiTransactionPayload>;
14
14
  export declare function pauseResumePayroll(program: Program<ZebecPayrollIdl>, params: PauseResumePayrollParams): Promise<TransactionPayload>;
@@ -27,3 +27,13 @@ export declare function cancelUnlock(payrollProgram: Program<ZebecPayrollIdl>, p
27
27
  export declare function completeUnlock(payrollProgram: Program<ZebecPayrollIdl>, configsProgram: Program<ZebecConfigsIdl>, params: CompleteUnlockParams, commitment?: Commitment): Promise<TransactionPayload>;
28
28
  export declare function distributeRewards(payrollProgram: Program<ZebecPayrollIdl>, configsProgram: Program<ZebecConfigsIdl>, params: DistributeRewardsParams): Promise<TransactionPayload>;
29
29
  export declare function getCompanyDeposit(payrollProgram: Program<ZebecPayrollIdl>, company: Address): Promise<CompanyDepositInfo | null>;
30
+ export declare function createCard(payrollProgram: Program<ZebecPayrollIdl>, configsProgram: Program<ZebecConfigsIdl>, params: {
31
+ currency: string;
32
+ reloadCardId: string;
33
+ nextCardIndex: bigint;
34
+ user: Address;
35
+ feePayer: Address;
36
+ emailHash: Buffer | Uint8Array;
37
+ amount: Numeric;
38
+ entCardConfigName: string;
39
+ }): Promise<TransactionPayload>;
package/dist/services.js CHANGED
@@ -3,14 +3,16 @@ import { fetchMetadata, MPL_TOKEN_METADATA_PROGRAM_ID, } from "@metaplex-foundat
3
3
  import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
4
4
  import { fromWeb3JsPublicKey, toWeb3JsPublicKey, } from "@metaplex-foundation/umi-web3js-adapters";
5
5
  import { Keypair, PublicKey, } from "@solana/web3.js";
6
- import { bpsToPercent, percentToBps } from "@zebec-network/core-utils";
7
- import { createAssociatedTokenAccountInstruction, getAssociatedTokenAddressSync, getMintDecimals, MultiTransactionPayload, TEN_BIGNUM, TransactionPayload, UNITS_PER_USDC, } from "@zebec-network/solana-common";
6
+ import { assertBufferSize, bpsToPercent, percentToBps, } from "@zebec-network/core-utils";
7
+ import { getAssociatedTokenAddressSync, getMintDecimals, MultiTransactionPayload, TEN_BIGNUM, TransactionPayload, UNITS_PER_USDC, USDC_DECIMALS, } from "@zebec-network/solana-common";
8
8
  import { BigNumber } from "bignumber.js";
9
9
  import { BN } from "bn.js";
10
10
  import { PAYROLL_NAME_BUFFER_SIZE, USX_DECIMALS } from "./constants.js";
11
- import { createCancelPayrollInstruction, createCancelUnlockInstruction, createChangeRecipientInstruction, createCompleteUnlockInstruction, createCreatePayrollInstruction, createDistributeRewardsInstruction, createPauseResumePayrollInstruction, createRequestUnlockInstruction, createSetTopupDelegateInstruction, createTopupPayrollInstruction, createTransferFeesInstruction, createWithdrawPayrollInstruction, createYieldDepositInstruction, } from "./instructions.js";
12
- import { deriveCheckAccountPda, deriveCompanyDepositPda, deriveCompanyNoncePda, derivePayrollConfigPda, derivePayrollVaultPda, deriveYieldConfigPda, } from "./pda.js";
13
- import { getFeeInfoForPayroll } from "./utils.js";
11
+ import { createCancelPayrollInstruction, createCancelUnlockInstruction, createChangeRecipientInstruction, createCompleteUnlockInstruction, createCreateCardInstruction, createCreatePayrollInstruction, createDistributeRewardsInstruction, createPauseResumePayrollInstruction, createRequestUnlockInstruction, createSetTopupDelegateInstruction, createTopupPayrollInstruction, createWithdrawPayrollInstruction, createYieldDepositInstruction, } from "./instructions.js";
12
+ import { deriveCheckAccountPda, deriveCompanyDepositPda, deriveCompanyNoncePda, deriveEnterpriseCardConfigPda, deriveEnterpriseCardIndexPda, deriveEnterpriseCardPurchasePda, deriveEnterpriseUserPurchaseRecordPda, derivePayrollConfigPda, derivePayrollVaultPda, deriveYieldConfigPda, } from "./pda.js";
13
+ import { deductFeeFromAmount, getConnectionFromProgram,
14
+ // getFeeInfoForPayroll,
15
+ getFeeRateForMint, isAmountWithInProviderCardPurchaseRange, isAmountWithinDailyCardLimit, } from "./utils.js";
14
16
  export async function getPayrollConfig(configProgram, configName) {
15
17
  const [payrollConfigPda] = derivePayrollConfigPda(configName, configProgram.programId);
16
18
  const payrollConfig = await configProgram.account.payrollConfig.fetchNullable(payrollConfigPda);
@@ -202,7 +204,7 @@ function createMultiTransactionPayload(program, feePayer, transactionData) {
202
204
  feePayer,
203
205
  })), signAllTransactions);
204
206
  }
205
- export async function createPayroll(payrollProgram, configProgram, params, payrollFeeBaseUrl) {
207
+ export async function createPayroll(payrollProgram, configProgram, params, _payrollFeeBaseUrl) {
206
208
  const receiver = translateAddress(params.receiver);
207
209
  const sender = translateAddress(params.sender);
208
210
  const feePayer = params.feePayer ? translateAddress(params.feePayer) : sender;
@@ -233,32 +235,57 @@ export async function createPayroll(payrollProgram, configProgram, params, payro
233
235
  const cliffPercentage = new BN(percentToBps(params.cliffPercentage));
234
236
  const payrollRunId = new Uint8Array(PAYROLL_NAME_BUFFER_SIZE);
235
237
  payrollRunId.set(utils.bytes.utf8.encode(params.payrollRunId));
236
- const feeInfo = await getFeeInfoForPayroll(payrollFeeBaseUrl, payrollToken, amount);
237
- const feeTokenDecimals = await getMintDecimals(payrollProgram.provider.connection, payrollConfigAccount.feeToken);
238
- const parsedFeeAmount = feeInfo.feeAmountRaw;
239
- const feeVault = payrollConfigAccount.feeVault;
240
- const feeVaultAta = getAssociatedTokenAddressSync(payrollConfigAccount.feeToken, feeVault, true);
241
- const senderFeeTokenAta = getAssociatedTokenAddressSync(payrollConfigAccount.feeToken, sender, true);
242
- const feeVaultAtaInfo = await payrollProgram.provider.connection.getAccountInfo(feeVaultAta);
238
+ // const feeInfo = await getFeeInfoForPayroll(
239
+ // payrollFeeBaseUrl,
240
+ // payrollToken,
241
+ // amount,
242
+ // );
243
+ // const feeTokenDecimals = await getMintDecimals(
244
+ // payrollProgram.provider.connection,
245
+ // payrollConfigAccount.feeToken,
246
+ // );
247
+ // const parsedFeeAmount = feeInfo.feeAmountRaw;
248
+ // const feeVault = payrollConfigAccount.feeVault;
249
+ // const feeVaultAta = getAssociatedTokenAddressSync(
250
+ // payrollConfigAccount.feeToken,
251
+ // feeVault,
252
+ // true,
253
+ // );
254
+ // const senderFeeTokenAta = getAssociatedTokenAddressSync(
255
+ // payrollConfigAccount.feeToken,
256
+ // sender,
257
+ // true,
258
+ // );
259
+ // const feeVaultAtaInfo =
260
+ // await payrollProgram.provider.connection.getAccountInfo(feeVaultAta);
243
261
  const ixs = [];
244
- // add instruction to create fee vault ATA if it does not exist
245
- if (!feeVaultAtaInfo) {
246
- const createFeeVaultAtaIx = createAssociatedTokenAccountInstruction(feePayer, feeVaultAta, feeVault, payrollConfigAccount.feeToken);
247
- ixs.push(createFeeVaultAtaIx);
248
- }
262
+ // // add instruction to create fee vault ATA if it does not exist
263
+ // if (!feeVaultAtaInfo) {
264
+ // const createFeeVaultAtaIx = createAssociatedTokenAccountInstruction(
265
+ // feePayer,
266
+ // feeVaultAta,
267
+ // feeVault,
268
+ // payrollConfigAccount.feeToken,
269
+ // );
270
+ // ixs.push(createFeeVaultAtaIx);
271
+ // }
249
272
  // add instruction to transfer fee to fee vault
250
- const transferFeeIx = await createTransferFeesInstruction(payrollProgram, {
251
- feeVault,
252
- feeVaultTokenAccount: feeVaultAta,
253
- payrollConfig,
254
- sender,
255
- senderTokenAccount: senderFeeTokenAta,
256
- tokenMint: payrollConfigAccount.feeToken,
257
- }, {
258
- decimals: feeTokenDecimals,
259
- feeAmount: new BN(parsedFeeAmount),
260
- });
261
- ixs.push(transferFeeIx);
273
+ // const transferFeeIx = await createTransferFeesInstruction(
274
+ // payrollProgram,
275
+ // {
276
+ // feeVault,
277
+ // feeVaultTokenAccount: feeVaultAta,
278
+ // payrollConfig,
279
+ // sender,
280
+ // senderTokenAccount: senderFeeTokenAta,
281
+ // tokenMint: payrollConfigAccount.feeToken,
282
+ // },
283
+ // {
284
+ // decimals: feeTokenDecimals,
285
+ // feeAmount: new BN(parsedFeeAmount),
286
+ // },
287
+ // );
288
+ // ixs.push(transferFeeIx);
262
289
  const createpayrollIx = await createCreatePayrollInstruction(payrollProgram, {
263
290
  payrollConfig,
264
291
  feePayer,
@@ -297,7 +324,7 @@ export async function createPayroll(payrollProgram, configProgram, params, payro
297
324
  payrollMetadataKeypair,
298
325
  ]);
299
326
  }
300
- export async function createMultiplePayroll(payrollProgram, configProgram, params, payrollFeeBaseUrl) {
327
+ export async function createMultiplePayroll(payrollProgram, configProgram, params, _payrollFeeBaseUrl) {
301
328
  const sender = translateAddress(params.sender);
302
329
  const feePayer = params.feePayer ? translateAddress(params.feePayer) : sender;
303
330
  const senderId = Array.from(params.senderId);
@@ -330,32 +357,57 @@ export async function createMultiplePayroll(payrollProgram, configProgram, param
330
357
  const cliffPercentage = new BN(percentToBps(payroll.cliffPercentage));
331
358
  const payrollRunId = new Uint8Array(PAYROLL_NAME_BUFFER_SIZE);
332
359
  payrollRunId.set(utils.bytes.utf8.encode(payroll.payrollRunId));
333
- const feeInfo = await getFeeInfoForPayroll(payrollFeeBaseUrl, payrollToken, amount);
334
- const feeTokenDecimals = await getMintDecimals(payrollProgram.provider.connection, payrollConfigAccount.feeToken);
335
- const parsedFeeAmount = feeInfo.feeAmountRaw;
336
- const feeVault = payrollConfigAccount.feeVault;
337
- const feeVaultAta = getAssociatedTokenAddressSync(payrollConfigAccount.feeToken, feeVault, true);
338
- const senderFeeTokenAta = getAssociatedTokenAddressSync(payrollConfigAccount.feeToken, sender, true);
339
- const feeVaultAtaInfo = await payrollProgram.provider.connection.getAccountInfo(feeVaultAta);
360
+ // const feeInfo = await getFeeInfoForPayroll(
361
+ // payrollFeeBaseUrl,
362
+ // payrollToken,
363
+ // amount,
364
+ // );
365
+ // const feeTokenDecimals = await getMintDecimals(
366
+ // payrollProgram.provider.connection,
367
+ // payrollConfigAccount.feeToken,
368
+ // );
369
+ // const parsedFeeAmount = feeInfo.feeAmountRaw;
370
+ // const feeVault = payrollConfigAccount.feeVault;
371
+ // const feeVaultAta = getAssociatedTokenAddressSync(
372
+ // payrollConfigAccount.feeToken,
373
+ // feeVault,
374
+ // true,
375
+ // );
376
+ // const senderFeeTokenAta = getAssociatedTokenAddressSync(
377
+ // payrollConfigAccount.feeToken,
378
+ // sender,
379
+ // true,
380
+ // );
381
+ // const feeVaultAtaInfo =
382
+ // await payrollProgram.provider.connection.getAccountInfo(feeVaultAta);
340
383
  const instructions = [];
341
384
  // add instruction to create fee vault ATA if it does not exist
342
- if (!feeVaultAtaInfo) {
343
- const createFeeVaultAtaIx = createAssociatedTokenAccountInstruction(feePayer, feeVaultAta, feeVault, payrollConfigAccount.feeToken);
344
- instructions.push(createFeeVaultAtaIx);
345
- }
385
+ // if (!feeVaultAtaInfo) {
386
+ // const createFeeVaultAtaIx = createAssociatedTokenAccountInstruction(
387
+ // feePayer,
388
+ // feeVaultAta,
389
+ // feeVault,
390
+ // payrollConfigAccount.feeToken,
391
+ // );
392
+ // instructions.push(createFeeVaultAtaIx);
393
+ // }
346
394
  // add instruction to transfer fee to fee vault
347
- const transferFeeIx = await createTransferFeesInstruction(payrollProgram, {
348
- feeVault,
349
- feeVaultTokenAccount: feeVaultAta,
350
- payrollConfig,
351
- sender,
352
- senderTokenAccount: senderFeeTokenAta,
353
- tokenMint: payrollConfigAccount.feeToken,
354
- }, {
355
- decimals: feeTokenDecimals,
356
- feeAmount: new BN(parsedFeeAmount),
357
- });
358
- instructions.push(transferFeeIx);
395
+ // const transferFeeIx = await createTransferFeesInstruction(
396
+ // payrollProgram,
397
+ // {
398
+ // feeVault,
399
+ // feeVaultTokenAccount: feeVaultAta,
400
+ // payrollConfig,
401
+ // sender,
402
+ // senderTokenAccount: senderFeeTokenAta,
403
+ // tokenMint: payrollConfigAccount.feeToken,
404
+ // },
405
+ // {
406
+ // decimals: feeTokenDecimals,
407
+ // feeAmount: new BN(parsedFeeAmount),
408
+ // },
409
+ // );
410
+ // instructions.push(transferFeeIx);
359
411
  const createpayrollIx = await createCreatePayrollInstruction(payrollProgram, {
360
412
  payrollConfig,
361
413
  feePayer,
@@ -868,3 +920,120 @@ export async function getCompanyDeposit(payrollProgram, company) {
868
920
  : null,
869
921
  };
870
922
  }
923
+ export async function createCard(payrollProgram, configsProgram, params) {
924
+ const connection = getConnectionFromProgram(payrollProgram);
925
+ const user = translateAddress(params.user);
926
+ const feePayer = translateAddress(params.feePayer);
927
+ assertBufferSize(params.emailHash, 32);
928
+ const [enterpriseCardConfig] = deriveEnterpriseCardConfigPda(params.entCardConfigName, configsProgram.programId);
929
+ const cardConfigAccount = await configsProgram.account.enterpriseCardConfig.fetchNullable(enterpriseCardConfig, connection.commitment);
930
+ if (!cardConfigAccount) {
931
+ throw new Error(`CardConfigAccountNotFound: Enterprise Card Config Account does not exits for config name: ${params.entCardConfigName}`);
932
+ }
933
+ const usdcMint = cardConfigAccount.usdcMint;
934
+ const userAta = getAssociatedTokenAddressSync(usdcMint, user, true);
935
+ const cardVault = cardConfigAccount.cardVault;
936
+ const cardVaultAta = getAssociatedTokenAddressSync(usdcMint, cardVault, true);
937
+ const revenueVault = cardConfigAccount.revenueVault;
938
+ const revenueVaultAta = getAssociatedTokenAddressSync(usdcMint, revenueVault, true);
939
+ const [enterpriseCardIndex] = deriveEnterpriseCardIndexPda(params.entCardConfigName, payrollProgram.programId);
940
+ const [cardPurchasePda] = deriveEnterpriseCardPurchasePda(user, params.entCardConfigName, params.nextCardIndex, payrollProgram.programId);
941
+ const [userPurchaseRecordPda] = deriveEnterpriseUserPurchaseRecordPda(user, params.entCardConfigName, payrollProgram.programId);
942
+ const unitsPerUSDC = BigNumber(10).pow(USDC_DECIMALS);
943
+ const amount = BigNumber(params.amount)
944
+ .times(unitsPerUSDC)
945
+ .toFixed(0, BigNumber.ROUND_FLOOR);
946
+ const feeRateInBps = BigNumber(getFeeRateForMint(cardConfigAccount.customFees.feeMap, usdcMint));
947
+ const amountWithoutFee = deductFeeFromAmount(amount, feeRateInBps);
948
+ const userPurchaseRecord = await payrollProgram.account.userPurchaseRecord.fetchNullable(userPurchaseRecordPda, "confirmed");
949
+ if (userPurchaseRecord &&
950
+ !isAmountWithinDailyCardLimit(userPurchaseRecord.dateTimeInUnix.toNumber(), userPurchaseRecord.totalBoughtPerDay.toString(), cardConfigAccount.dailyCardBuyLimit.toString(), amountWithoutFee)) {
951
+ throw new Error("DailyCardLimitReachedError: " +
952
+ "Daily card limit reached. Limit: " +
953
+ BigNumber(cardConfigAccount.dailyCardBuyLimit.toString())
954
+ .div(unitsPerUSDC)
955
+ .toFixed() +
956
+ " Requested (Fee Deducted): " +
957
+ BigNumber(amountWithoutFee).div(unitsPerUSDC).toFixed());
958
+ }
959
+ if (!isAmountWithInProviderCardPurchaseRange(cardConfigAccount.providerConfig.minCardAmount.toString(), cardConfigAccount.providerConfig.maxCardAmount.toString(), amountWithoutFee)) {
960
+ throw new Error("AmountOfProviderCardPurchaseRange:" +
961
+ "Amount out of range: " +
962
+ BigNumber(amountWithoutFee).div(unitsPerUSDC).toFixed() +
963
+ "(Fee Deducted); Must be within " +
964
+ BigNumber(cardConfigAccount.providerConfig.minCardAmount.toString())
965
+ .div(unitsPerUSDC)
966
+ .toFixed() +
967
+ "-" +
968
+ BigNumber(cardConfigAccount.providerConfig.maxCardAmount.toString())
969
+ .div(unitsPerUSDC)
970
+ .toFixed());
971
+ }
972
+ const instruction = await createCreateCardInstruction(payrollProgram, {
973
+ cardPurchasePda,
974
+ cardVault,
975
+ cardVaultAta,
976
+ enterpriseCardConfig,
977
+ enterpriseCardIndex,
978
+ feePayer,
979
+ revenueVault,
980
+ revenueVaultAta,
981
+ usdcMint,
982
+ user,
983
+ userAta,
984
+ userPurchaseRecordPda,
985
+ }, {
986
+ amount: new BN(amount),
987
+ currency: params.currency,
988
+ emailHash: Array.from(params.emailHash),
989
+ index: new BN(params.nextCardIndex),
990
+ reloadCardId: params.reloadCardId,
991
+ });
992
+ return createTransactionPayload(payrollProgram, feePayer, [instruction]);
993
+ }
994
+ // export async function swapAndCreateCard(
995
+ // payrollProgram: Program<ZebecPayrollIdl>,
996
+ // configsProgram: Program<ZebecConfigsIdl>,
997
+ // params: {
998
+ // currency: string;
999
+ // reloadCardId: string;
1000
+ // nextCardIndex: bigint;
1001
+ // user: Address;
1002
+ // feePayer: Address;
1003
+ // emailHash: Buffer | Uint8Array;
1004
+ // amount: Numeric;
1005
+ // entCardConfigName: string;
1006
+ // quoteInfo: QuoteInfo;
1007
+ // }
1008
+ // ) {
1009
+ // const connection = getConnectionFromProgram(payrollProgram);
1010
+ // const user = translateAddress(params.user);
1011
+ // const feePayer = translateAddress(params.feePayer);
1012
+ // const quoteInfo = params.quoteInfo;
1013
+ // if ("error" in quoteInfo) {
1014
+ // throw new Error(quoteInfo.error);
1015
+ // }
1016
+ // assertBufferSize(params.emailHash, 32);
1017
+ // const [enterpriseCardConfig] = deriveEnterpriseCardConfigPda(
1018
+ // params.entCardConfigName,
1019
+ // configsProgram.programId,
1020
+ // );
1021
+ // const cardConfigAccount =
1022
+ // await configsProgram.account.enterpriseCardConfig.fetchNullable(
1023
+ // enterpriseCardConfig,
1024
+ // connection.commitment,
1025
+ // );
1026
+ // if (!cardConfigAccount) {
1027
+ // throw new Error(
1028
+ // `CardConfigAccountNotFound: Enterprise Card Config Account does not exits for config name: ${params.entCardConfigName}`,
1029
+ // );
1030
+ // }
1031
+ // const revenueVault = cardConfigAccount.revenueVault;
1032
+ // const cardVault = cardConfigAccount.cardVault;
1033
+ // const usdcMint = translateAddress(quoteInfo.outputMint);
1034
+ // if (!usdcMint.equals(cardConfigAccount.usdcMint)) {
1035
+ // throw new Error("InvalidUSDCMint: Output mint in quoteInfo in is not a usdc")
1036
+ // }
1037
+ // const inputMint = translateAddress(quoteInfo.inputMint);
1038
+ // // const
1039
+ // }
package/dist/types.d.ts CHANGED
@@ -274,3 +274,47 @@ export type CompanyDepositInfo = {
274
274
  requestTime: number;
275
275
  } | null;
276
276
  };
277
+ /**
278
+ * Jupiter quote routes info
279
+ */
280
+ export type RouteInfo = {
281
+ swapInfo: {
282
+ ammKey: string;
283
+ label: string;
284
+ inputMint: string;
285
+ outputMint: string;
286
+ inAmount: string;
287
+ outAmount: string;
288
+ feeAmount: string;
289
+ feeMint: string;
290
+ };
291
+ percent: number;
292
+ bps: number;
293
+ };
294
+ /**
295
+ * Jupiter quote info
296
+ */
297
+ export type QuoteInfo = {
298
+ inputMint: string;
299
+ inAmount: string;
300
+ outputMint: string;
301
+ outAmount: string;
302
+ otherAmountThreshold: string;
303
+ swapMode: "ExactIn" | "ExactOut";
304
+ slippageBps: number;
305
+ platformFee: {
306
+ amount: string;
307
+ feeBps: number;
308
+ } | null;
309
+ priceImpactPct: string;
310
+ routePlan: RouteInfo[];
311
+ contextSlot: number;
312
+ timeTaken: number;
313
+ swapUsdValue: string;
314
+ simplerRouteUsed: boolean;
315
+ mostReliableAmmsQuoteReport: {
316
+ info: Record<string, string>;
317
+ };
318
+ } | {
319
+ error: string;
320
+ };
package/dist/utils.d.ts CHANGED
@@ -1,5 +1,16 @@
1
- import type { Address } from "@coral-xyz/anchor";
1
+ import type { Address, Idl, Program } from "@coral-xyz/anchor";
2
+ import type { PublicKey } from "@solana/web3.js";
2
3
  import { BigNumber } from "bignumber.js";
4
+ import type BN from "bn.js";
3
5
  import type { FeeTier, PayrollFeeInfo } from "./types.js";
4
6
  export declare function getFeeInfoForPayroll(baseUrl: string, payrollToken: Address, parsedStreamTokenAmount: BigNumber.Value): Promise<PayrollFeeInfo>;
5
7
  export declare function getFeeRateForUsdAmount(amount: BigNumber.Value, feeTiers: FeeTier[]): string;
8
+ export declare function getConnectionFromProgram<T extends Idl>(program: Program<T>): import("@solana/web3.js").Connection;
9
+ export declare function isAmountWithinDailyCardLimit(lastCardBoughtUnixTimestamp: number, lastCardBoughtRawAmountPerDay: BigNumber.Value, rawDailyCardBuyLimit: BigNumber.Value, rawAmount: BigNumber.Value): boolean;
10
+ export declare function isAmountWithInProviderCardPurchaseRange(rawMinCardAmount: BigNumber.Value, rawMaxCardAmount: BigNumber.Value, rawAmount: BigNumber.Value): boolean;
11
+ export type ParsedTokenFeeItem = {
12
+ tokenAddress: PublicKey;
13
+ fee: BN;
14
+ };
15
+ export declare function getFeeRateForMint(feeRateList: ParsedTokenFeeItem[], mint: PublicKey): number;
16
+ export declare function deductFeeFromAmount(rawAmount: BigNumber.Value, feeRateInBps: BigNumber.Value): string;
package/dist/utils.js CHANGED
@@ -1,5 +1,6 @@
1
- import { percentToBps } from "@zebec-network/core-utils";
1
+ import { areDatesOfSameDay, percentToBps } from "@zebec-network/core-utils";
2
2
  import { BigNumber } from "bignumber.js";
3
+ import { BPS_DENOMINATOR, DEFAULT_FEE_RATE_IN_BPS } from "./constants.js";
3
4
  export async function getFeeInfoForPayroll(baseUrl, payrollToken, parsedStreamTokenAmount) {
4
5
  const urlsParams = new URLSearchParams({
5
6
  tokenMint: payrollToken.toString(),
@@ -60,3 +61,41 @@ export function getFeeRateForUsdAmount(amount, feeTiers) {
60
61
  }
61
62
  return percentToBps(tier.feeRateInPercent);
62
63
  }
64
+ export function getConnectionFromProgram(program) {
65
+ return program.provider.connection;
66
+ }
67
+ export function isAmountWithinDailyCardLimit(lastCardBoughtUnixTimestamp, lastCardBoughtRawAmountPerDay, rawDailyCardBuyLimit, rawAmount) {
68
+ const dailyCardBuyLimit = BigNumber(rawDailyCardBuyLimit);
69
+ const amount = BigNumber(rawAmount);
70
+ const today = new Date();
71
+ const lastCardBoughtDate = new Date(lastCardBoughtUnixTimestamp * 1000);
72
+ let cardBoughtInADay = BigNumber(0);
73
+ if (areDatesOfSameDay(today, lastCardBoughtDate)) {
74
+ cardBoughtInADay = BigNumber(lastCardBoughtRawAmountPerDay).plus(amount);
75
+ }
76
+ else {
77
+ cardBoughtInADay = amount;
78
+ }
79
+ if (cardBoughtInADay.isGreaterThan(dailyCardBuyLimit)) {
80
+ return false;
81
+ }
82
+ return true;
83
+ }
84
+ export function isAmountWithInProviderCardPurchaseRange(rawMinCardAmount, rawMaxCardAmount, rawAmount) {
85
+ const minRange = BigNumber(rawMinCardAmount);
86
+ const maxRange = BigNumber(rawMaxCardAmount);
87
+ const amount = BigNumber(rawAmount);
88
+ if (amount.isLessThan(minRange) || amount.isGreaterThan(maxRange)) {
89
+ return false;
90
+ }
91
+ return true;
92
+ }
93
+ export function getFeeRateForMint(feeRateList, mint) {
94
+ return (feeRateList.find((fr) => fr.tokenAddress.equals(mint))?.fee.toNumber() ||
95
+ DEFAULT_FEE_RATE_IN_BPS);
96
+ }
97
+ export function deductFeeFromAmount(rawAmount, feeRateInBps) {
98
+ const amount = BigNumber(rawAmount);
99
+ const fee = amount.times(feeRateInBps).div(BPS_DENOMINATOR);
100
+ return amount.minus(fee).toFixed(0, BigNumber.ROUND_FLOOR);
101
+ }
package/package.json CHANGED
@@ -9,10 +9,11 @@
9
9
  "@solana/spl-token": "^0.4.14",
10
10
  "@solana/web3.js": "^1.98.2",
11
11
  "@zebec-network/core-utils": "^1.3.1",
12
- "@zebec-network/solana-common": "^2.6.0",
13
- "@zebec-network/zebec_configs": "^1.2.3",
14
- "@zebec-network/zebec_payroll": "^1.5.0",
15
- "bignumber.js": "^11.1.1"
12
+ "@zebec-network/solana-common": "^2.6.1",
13
+ "@zebec-network/zebec_configs": "^1.2.6",
14
+ "@zebec-network/zebec_payroll": "^1.5.2",
15
+ "bignumber.js": "^11.1.1",
16
+ "bn.js": "^5.2.3"
16
17
  },
17
18
  "devDependencies": {
18
19
  "@types/bn.js": "^5.2.0",
@@ -43,5 +44,5 @@
43
44
  },
44
45
  "type": "module",
45
46
  "types": "dist/index.d.ts",
46
- "version": "2.5.0"
47
+ "version": "2.6.0-dev.1"
47
48
  }