payment-kit 1.18.14 → 1.18.16
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/api/src/index.ts +2 -0
- package/api/src/libs/invoice.ts +5 -3
- package/api/src/routes/connect/change-payment.ts +9 -1
- package/api/src/routes/connect/change-plan.ts +9 -1
- package/api/src/routes/connect/collect-batch.ts +7 -5
- package/api/src/routes/connect/recharge-account.ts +124 -0
- package/api/src/routes/connect/setup.ts +8 -1
- package/api/src/routes/connect/shared.ts +110 -48
- package/api/src/routes/connect/subscribe.ts +11 -1
- package/api/src/routes/customers.ts +149 -6
- package/api/src/routes/invoices.ts +46 -0
- package/api/src/routes/payment-currencies.ts +5 -2
- package/api/src/routes/subscriptions.ts +0 -3
- package/blocklet.yml +1 -1
- package/package.json +8 -8
- package/src/app.tsx +11 -3
- package/src/components/info-card.tsx +3 -1
- package/src/components/info-row.tsx +1 -0
- package/src/components/invoice/recharge.tsx +85 -56
- package/src/components/invoice/table.tsx +7 -1
- package/src/components/subscription/portal/actions.tsx +1 -1
- package/src/components/subscription/portal/list.tsx +6 -0
- package/src/locales/en.tsx +9 -0
- package/src/locales/zh.tsx +9 -0
- package/src/pages/admin/settings/vault-config/index.tsx +21 -6
- package/src/pages/customer/index.tsx +160 -265
- package/src/pages/customer/invoice/detail.tsx +24 -16
- package/src/pages/customer/invoice/past-due.tsx +45 -23
- package/src/pages/customer/recharge/account.tsx +515 -0
- package/src/pages/customer/{recharge.tsx → recharge/subscription.tsx} +11 -11
- package/src/pages/customer/subscription/embed.tsx +16 -1
package/api/src/index.ts
CHANGED
|
@@ -39,6 +39,7 @@ import setupHandlers from './routes/connect/setup';
|
|
|
39
39
|
import subscribeHandlers from './routes/connect/subscribe';
|
|
40
40
|
import delegationHandlers from './routes/connect/delegation';
|
|
41
41
|
import overdraftProtectionHandlers from './routes/connect/overdraft-protection';
|
|
42
|
+
import rechargeAccountHandlers from './routes/connect/recharge-account';
|
|
42
43
|
import { initialize } from './store/models';
|
|
43
44
|
import { sequelize } from './store/sequelize';
|
|
44
45
|
import { initUserHandler } from './integrations/blocklet/user';
|
|
@@ -74,6 +75,7 @@ handlers.attach(Object.assign({ app: router }, subscribeHandlers));
|
|
|
74
75
|
handlers.attach(Object.assign({ app: router }, changePaymentHandlers));
|
|
75
76
|
handlers.attach(Object.assign({ app: router }, changePlanHandlers));
|
|
76
77
|
handlers.attach(Object.assign({ app: router }, rechargeHandlers));
|
|
78
|
+
handlers.attach(Object.assign({ app: router }, rechargeAccountHandlers));
|
|
77
79
|
handlers.attach(Object.assign({ app: router }, delegationHandlers));
|
|
78
80
|
handlers.attach(Object.assign({ app: router }, overdraftProtectionHandlers));
|
|
79
81
|
router.use('/api', routes);
|
package/api/src/libs/invoice.ts
CHANGED
|
@@ -363,7 +363,7 @@ export async function getStakingInvoices(subscription: Subscription): Promise<In
|
|
|
363
363
|
|
|
364
364
|
type BaseInvoiceProps = {
|
|
365
365
|
customer: Customer;
|
|
366
|
-
subscription?: Subscription;
|
|
366
|
+
subscription?: Subscription | null;
|
|
367
367
|
currency_id: string;
|
|
368
368
|
livemode: boolean;
|
|
369
369
|
period_start: number;
|
|
@@ -660,17 +660,19 @@ export async function ensureRechargeInvoice(
|
|
|
660
660
|
currency_id: string;
|
|
661
661
|
metadata?: any;
|
|
662
662
|
payment_settings?: any;
|
|
663
|
+
livemode?: boolean;
|
|
663
664
|
},
|
|
664
|
-
subscription: Subscription,
|
|
665
|
+
subscription: Subscription | null,
|
|
665
666
|
paymentMethod: PaymentMethod,
|
|
666
667
|
customer: Customer
|
|
667
668
|
) {
|
|
668
669
|
try {
|
|
670
|
+
const { livemode = true } = invoiceProps;
|
|
669
671
|
const { invoice } = await createInvoiceWithItems({
|
|
670
672
|
customer,
|
|
671
673
|
subscription,
|
|
672
674
|
currency_id: invoiceProps.currency_id,
|
|
673
|
-
livemode: subscription
|
|
675
|
+
livemode: subscription?.livemode ?? livemode,
|
|
674
676
|
period_start: dayjs().unix(),
|
|
675
677
|
period_end: dayjs().unix(),
|
|
676
678
|
status: 'paid',
|
|
@@ -99,6 +99,9 @@ export default {
|
|
|
99
99
|
result.push({
|
|
100
100
|
step,
|
|
101
101
|
claim: claims?.[0],
|
|
102
|
+
stepRequest: {
|
|
103
|
+
headers: request?.headers,
|
|
104
|
+
},
|
|
102
105
|
});
|
|
103
106
|
|
|
104
107
|
// 判断是否为最后一步
|
|
@@ -164,12 +167,17 @@ export default {
|
|
|
164
167
|
|
|
165
168
|
if (paymentMethod.type === 'arcblock') {
|
|
166
169
|
await prepareTxExecution();
|
|
170
|
+
const requestArray = result
|
|
171
|
+
.map((item: { stepRequest?: Request }) => item.stepRequest)
|
|
172
|
+
.filter(Boolean) as Request[];
|
|
173
|
+
const requestSource = requestArray.length > 0 ? requestArray : request;
|
|
174
|
+
|
|
167
175
|
const { stakingAmount, ...paymentDetails } = await executeOcapTransactions(
|
|
168
176
|
userDid,
|
|
169
177
|
userPk,
|
|
170
178
|
claimsList,
|
|
171
179
|
paymentMethod,
|
|
172
|
-
|
|
180
|
+
requestSource,
|
|
173
181
|
subscription?.id,
|
|
174
182
|
paymentCurrency.contract
|
|
175
183
|
);
|
|
@@ -113,6 +113,9 @@ export default {
|
|
|
113
113
|
result.push({
|
|
114
114
|
step,
|
|
115
115
|
claim: claims?.[0],
|
|
116
|
+
stepRequest: {
|
|
117
|
+
headers: request?.headers,
|
|
118
|
+
},
|
|
116
119
|
});
|
|
117
120
|
|
|
118
121
|
// 判断是否为最后一步
|
|
@@ -171,12 +174,17 @@ export default {
|
|
|
171
174
|
if (paymentMethod.type === 'arcblock') {
|
|
172
175
|
await prepareTxExecution();
|
|
173
176
|
|
|
177
|
+
const requestArray = result
|
|
178
|
+
.map((item: { stepRequest?: Request }) => item.stepRequest)
|
|
179
|
+
.filter(Boolean) as Request[];
|
|
180
|
+
const requestSource = requestArray.length > 0 ? requestArray : request;
|
|
181
|
+
|
|
174
182
|
const { stakingAmount, ...paymentDetails } = await executeOcapTransactions(
|
|
175
183
|
userDid,
|
|
176
184
|
userPk,
|
|
177
185
|
claimsList,
|
|
178
186
|
paymentMethod,
|
|
179
|
-
|
|
187
|
+
requestSource,
|
|
180
188
|
subscription?.id,
|
|
181
189
|
paymentCurrency?.contract
|
|
182
190
|
);
|
|
@@ -23,16 +23,18 @@ export default {
|
|
|
23
23
|
authPrincipal: async ({ extraParams }: CallbackArgs) => {
|
|
24
24
|
const { paymentMethod } = await ensureSubscriptionForCollectBatch(
|
|
25
25
|
extraParams.subscriptionId,
|
|
26
|
-
extraParams.currencyId
|
|
26
|
+
extraParams.currencyId,
|
|
27
|
+
extraParams.customerId
|
|
27
28
|
);
|
|
28
29
|
return getAuthPrincipalClaim(paymentMethod, 'pay');
|
|
29
30
|
},
|
|
30
31
|
},
|
|
31
32
|
onConnect: async ({ userDid, userPk, extraParams }: CallbackArgs) => {
|
|
32
|
-
const { subscriptionId, currencyId } = extraParams;
|
|
33
|
+
const { subscriptionId, currencyId, customerId } = extraParams;
|
|
33
34
|
const { amount, invoices, paymentCurrency, paymentMethod } = await ensureSubscriptionForCollectBatch(
|
|
34
35
|
subscriptionId,
|
|
35
|
-
currencyId
|
|
36
|
+
currencyId,
|
|
37
|
+
customerId
|
|
36
38
|
);
|
|
37
39
|
|
|
38
40
|
if (paymentMethod.type === 'arcblock') {
|
|
@@ -83,8 +85,8 @@ export default {
|
|
|
83
85
|
throw new Error(`Payment method ${paymentMethod.type} not supported`);
|
|
84
86
|
},
|
|
85
87
|
onAuth: async ({ request, userDid, claims, extraParams }: CallbackArgs) => {
|
|
86
|
-
const { subscriptionId, currencyId } = extraParams;
|
|
87
|
-
const { invoices, paymentMethod } = await ensureSubscriptionForCollectBatch(subscriptionId, currencyId);
|
|
88
|
+
const { subscriptionId, currencyId, customerId } = extraParams;
|
|
89
|
+
const { invoices, paymentMethod } = await ensureSubscriptionForCollectBatch(subscriptionId, currencyId, customerId);
|
|
88
90
|
|
|
89
91
|
const afterTxExecution = async (paymentDetails: any) => {
|
|
90
92
|
const paymentIntents = await PaymentIntent.findAll({
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { Transaction } from '@ocap/client';
|
|
2
|
+
import { fromAddress } from '@ocap/wallet';
|
|
3
|
+
import { fromTokenToUnit } from '@ocap/util';
|
|
4
|
+
import type { CallbackArgs } from '../../libs/auth';
|
|
5
|
+
import { getGasPayerExtra } from '../../libs/payment';
|
|
6
|
+
import { getTxMetadata } from '../../libs/util';
|
|
7
|
+
import { ensureAccountRecharge, getAuthPrincipalClaim } from './shared';
|
|
8
|
+
import logger from '../../libs/logger';
|
|
9
|
+
import { ensureRechargeInvoice } from '../../libs/invoice';
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
action: 'recharge-account',
|
|
13
|
+
authPrincipal: false,
|
|
14
|
+
claims: {
|
|
15
|
+
authPrincipal: async ({ extraParams }: CallbackArgs) => {
|
|
16
|
+
const { paymentMethod } = await ensureAccountRecharge(extraParams.customerDid, extraParams.currencyId);
|
|
17
|
+
return getAuthPrincipalClaim(paymentMethod, 'recharge-account');
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
onConnect: async ({ userDid, userPk, extraParams }: CallbackArgs) => {
|
|
21
|
+
const { customerDid, currencyId } = extraParams;
|
|
22
|
+
let { amount } = extraParams;
|
|
23
|
+
const { paymentMethod, paymentCurrency, customer } = await ensureAccountRecharge(customerDid, currencyId);
|
|
24
|
+
amount = fromTokenToUnit(amount, paymentCurrency.decimal).toString();
|
|
25
|
+
if (paymentMethod.type === 'arcblock') {
|
|
26
|
+
const tokens = [{ address: paymentCurrency.contract as string, value: amount }];
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
const itx: TransferV3Tx = {
|
|
29
|
+
outputs: [{ owner: customerDid, tokens, assets: [] }],
|
|
30
|
+
data: getTxMetadata({
|
|
31
|
+
rechargeCustomerId: customer.id,
|
|
32
|
+
customerDid,
|
|
33
|
+
currencyId: paymentCurrency.id,
|
|
34
|
+
amount,
|
|
35
|
+
action: 'recharge-account',
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const claims: { [key: string]: object } = {
|
|
40
|
+
prepareTx: {
|
|
41
|
+
type: 'TransferV3Tx',
|
|
42
|
+
description: `Recharge account for ${customerDid}`,
|
|
43
|
+
partialTx: { from: userDid, pk: userPk, itx },
|
|
44
|
+
requirement: { tokens },
|
|
45
|
+
chainInfo: {
|
|
46
|
+
host: paymentMethod.settings?.arcblock?.api_host as string,
|
|
47
|
+
id: paymentMethod.settings?.arcblock?.chain_id as string,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return claims;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
throw new Error(`Payment method ${paymentMethod.type} not supported`);
|
|
56
|
+
},
|
|
57
|
+
onAuth: async ({ request, userDid, claims, extraParams }: CallbackArgs) => {
|
|
58
|
+
const { customerDid, currencyId } = extraParams;
|
|
59
|
+
const { paymentMethod, paymentCurrency, customer } = await ensureAccountRecharge(customerDid, currencyId);
|
|
60
|
+
let { amount } = extraParams;
|
|
61
|
+
amount = fromTokenToUnit(amount, paymentCurrency.decimal).toString();
|
|
62
|
+
|
|
63
|
+
const afterTxExecution = async (paymentDetails: any) => {
|
|
64
|
+
await ensureRechargeInvoice(
|
|
65
|
+
{
|
|
66
|
+
total: amount,
|
|
67
|
+
description: 'Add funds for account',
|
|
68
|
+
currency_id: paymentCurrency.id,
|
|
69
|
+
metadata: {
|
|
70
|
+
payment_details: {
|
|
71
|
+
[paymentMethod.type]: paymentDetails,
|
|
72
|
+
receiverAddress: customerDid,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
livemode: paymentCurrency?.livemode,
|
|
76
|
+
payment_settings: {
|
|
77
|
+
payment_method_types: [paymentMethod.type],
|
|
78
|
+
payment_method_options: {
|
|
79
|
+
[paymentMethod.type]: {
|
|
80
|
+
payer: userDid,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
null,
|
|
86
|
+
paymentMethod,
|
|
87
|
+
customer!
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
if (paymentMethod.type === 'arcblock') {
|
|
91
|
+
try {
|
|
92
|
+
const client = paymentMethod.getOcapClient();
|
|
93
|
+
const claim = claims.find((x) => x.type === 'prepareTx');
|
|
94
|
+
|
|
95
|
+
const tx: Partial<Transaction> = client.decodeTx(claim.finalTx);
|
|
96
|
+
if (claim.delegator && claim.from) {
|
|
97
|
+
tx.delegator = claim.delegator;
|
|
98
|
+
tx.from = claim.from;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// @ts-ignore
|
|
102
|
+
const { buffer } = await client.encodeTransferV3Tx({ tx });
|
|
103
|
+
const txHash = await client.sendTransferV3Tx(
|
|
104
|
+
// @ts-ignore
|
|
105
|
+
{ tx, wallet: fromAddress(userDid) },
|
|
106
|
+
getGasPayerExtra(buffer, client.pickGasPayerHeaders(request))
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
await afterTxExecution({
|
|
110
|
+
tx_hash: txHash,
|
|
111
|
+
payer: userDid,
|
|
112
|
+
type: 'transfer',
|
|
113
|
+
});
|
|
114
|
+
return { hash: txHash };
|
|
115
|
+
} catch (err) {
|
|
116
|
+
console.error(err);
|
|
117
|
+
logger.error('Failed to finalize recharge on arcblock', { receiverAddress: customerDid, error: err });
|
|
118
|
+
throw err;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
throw new Error(`Payment method ${paymentMethod.type} not supported`);
|
|
123
|
+
},
|
|
124
|
+
};
|
|
@@ -132,6 +132,9 @@ export default {
|
|
|
132
132
|
result.push({
|
|
133
133
|
step,
|
|
134
134
|
claim: claims?.[0],
|
|
135
|
+
stepRequest: {
|
|
136
|
+
headers: request?.headers,
|
|
137
|
+
},
|
|
135
138
|
});
|
|
136
139
|
|
|
137
140
|
// 判断是否为最后一步
|
|
@@ -199,13 +202,17 @@ export default {
|
|
|
199
202
|
if (paymentMethod.type === 'arcblock') {
|
|
200
203
|
try {
|
|
201
204
|
await prepareTxExecution();
|
|
205
|
+
const requestArray = result
|
|
206
|
+
.map((item: { stepRequest?: Request }) => item.stepRequest)
|
|
207
|
+
.filter(Boolean) as Request[];
|
|
208
|
+
const requestSource = requestArray.length > 0 ? requestArray : request;
|
|
202
209
|
|
|
203
210
|
const { stakingAmount, ...paymentDetails } = await executeOcapTransactions(
|
|
204
211
|
userDid,
|
|
205
212
|
userPk,
|
|
206
213
|
claimsList,
|
|
207
214
|
paymentMethod,
|
|
208
|
-
|
|
215
|
+
requestSource,
|
|
209
216
|
subscription?.id,
|
|
210
217
|
paymentCurrency?.contract
|
|
211
218
|
);
|
|
@@ -6,7 +6,7 @@ import type { Transaction } from '@ocap/client';
|
|
|
6
6
|
import { BN, fromTokenToUnit, toBase58 } from '@ocap/util';
|
|
7
7
|
import { fromPublicKey } from '@ocap/wallet';
|
|
8
8
|
import type { Request } from 'express';
|
|
9
|
-
import isEmpty from 'lodash
|
|
9
|
+
import { isEmpty } from 'lodash';
|
|
10
10
|
|
|
11
11
|
import { estimateMaxGasForTx, hasStakedForGas } from '../../integrations/arcblock/stake';
|
|
12
12
|
import { encodeApproveItx } from '../../integrations/ethereum/token';
|
|
@@ -481,6 +481,25 @@ export async function ensureSubscriptionRecharge(subscriptionId: string) {
|
|
|
481
481
|
};
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
+
export async function ensureAccountRecharge(customerId: string, currencyId: string) {
|
|
485
|
+
const customer = await Customer.findByPkOrDid(customerId);
|
|
486
|
+
if (!customer) {
|
|
487
|
+
throw new Error(`Customer ${customerId} not found`);
|
|
488
|
+
}
|
|
489
|
+
const paymentCurrency = await PaymentCurrency.findByPk(currencyId);
|
|
490
|
+
if (!paymentCurrency) {
|
|
491
|
+
throw new Error(`Currency ${currencyId} not found`);
|
|
492
|
+
}
|
|
493
|
+
const paymentMethod = await PaymentMethod.findByPk(paymentCurrency.payment_method_id);
|
|
494
|
+
if (!paymentMethod) {
|
|
495
|
+
throw new Error(`Payment method ${paymentCurrency.payment_method_id} not found`);
|
|
496
|
+
}
|
|
497
|
+
return {
|
|
498
|
+
paymentCurrency: paymentCurrency as PaymentCurrency,
|
|
499
|
+
paymentMethod: paymentMethod as PaymentMethod,
|
|
500
|
+
customer,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
484
503
|
export function getAuthPrincipalClaim(method: PaymentMethod, action: string) {
|
|
485
504
|
let chainInfo = { type: 'none', id: 'none', host: 'none' };
|
|
486
505
|
if (method.type === 'arcblock') {
|
|
@@ -934,10 +953,16 @@ export async function ensureChangePaymentContext(subscriptionId: string) {
|
|
|
934
953
|
};
|
|
935
954
|
}
|
|
936
955
|
|
|
937
|
-
export async function ensureSubscriptionForCollectBatch(
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
956
|
+
export async function ensureSubscriptionForCollectBatch(
|
|
957
|
+
subscriptionId?: string,
|
|
958
|
+
currencyId?: string,
|
|
959
|
+
customerId?: string
|
|
960
|
+
) {
|
|
961
|
+
if (!currencyId) {
|
|
962
|
+
throw new Error('Currency ID must be provided');
|
|
963
|
+
}
|
|
964
|
+
if (!subscriptionId && !customerId) {
|
|
965
|
+
throw new Error('Either subscriptionId or customerId must be provided');
|
|
941
966
|
}
|
|
942
967
|
|
|
943
968
|
const paymentCurrency = await PaymentCurrency.findByPk(currencyId);
|
|
@@ -945,16 +970,36 @@ export async function ensureSubscriptionForCollectBatch(subscriptionId: string,
|
|
|
945
970
|
throw new Error(`PaymentCurrency ${currencyId} not found when prepare batch collect`);
|
|
946
971
|
}
|
|
947
972
|
|
|
973
|
+
let subscription;
|
|
974
|
+
let searchCustomerId = customerId;
|
|
975
|
+
|
|
976
|
+
if (subscriptionId) {
|
|
977
|
+
subscription = await Subscription.findByPk(subscriptionId);
|
|
978
|
+
if (!subscription) {
|
|
979
|
+
throw new Error(`Subscription ${subscriptionId} not found when prepare batch collect`);
|
|
980
|
+
}
|
|
981
|
+
searchCustomerId = subscription.customer_id;
|
|
982
|
+
} else if (customerId) {
|
|
983
|
+
const customer = await Customer.findByPkOrDid(customerId);
|
|
984
|
+
if (!customer) {
|
|
985
|
+
throw new Error(`Customer ${customerId} not found when prepare batch collect`);
|
|
986
|
+
}
|
|
987
|
+
searchCustomerId = customer.id;
|
|
988
|
+
}
|
|
989
|
+
|
|
948
990
|
const [summary, detail] = await Invoice.getUncollectibleAmount({
|
|
949
|
-
subscriptionId:
|
|
950
|
-
customerId:
|
|
991
|
+
...(subscriptionId ? { subscriptionId } : {}),
|
|
992
|
+
customerId: searchCustomerId,
|
|
951
993
|
currencyId,
|
|
952
994
|
});
|
|
953
995
|
if (isEmpty(summary) || !summary[currencyId] || summary[currencyId] === '0') {
|
|
954
|
-
throw new Error(
|
|
996
|
+
throw new Error('No uncollectible invoice found to batch collect');
|
|
955
997
|
}
|
|
956
998
|
|
|
957
999
|
const paymentMethod = await PaymentMethod.findByPk(paymentCurrency.payment_method_id);
|
|
1000
|
+
if (!paymentMethod) {
|
|
1001
|
+
throw new Error(`Payment method not found for currency ${currencyId}`);
|
|
1002
|
+
}
|
|
958
1003
|
|
|
959
1004
|
return {
|
|
960
1005
|
subscription,
|
|
@@ -1005,7 +1050,7 @@ export async function executeOcapTransactions(
|
|
|
1005
1050
|
userPk: string,
|
|
1006
1051
|
claims: any[],
|
|
1007
1052
|
paymentMethod: PaymentMethod,
|
|
1008
|
-
|
|
1053
|
+
requestSource: Request | Request[] | any[],
|
|
1009
1054
|
subscriptionId?: string,
|
|
1010
1055
|
paymentCurrencyContract?: string,
|
|
1011
1056
|
nonce?: string
|
|
@@ -1022,47 +1067,64 @@ export async function executeOcapTransactions(
|
|
|
1022
1067
|
const stakingAmount =
|
|
1023
1068
|
staking?.requirement?.tokens?.find((x: any) => x.address === paymentCurrencyContract)?.value || '0';
|
|
1024
1069
|
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
// @ts-ignore
|
|
1038
|
-
const { buffer } = await client[`encode${type}Tx`]({ tx });
|
|
1039
|
-
// @ts-ignore
|
|
1040
|
-
const txHash = await client[`send${type}Tx`](
|
|
1041
|
-
// @ts-ignore
|
|
1042
|
-
{ tx, wallet: fromPublicKey(userPk, toTypeInfo(userDid)) },
|
|
1043
|
-
getGasPayerExtra(buffer, client.pickGasPayerHeaders(request))
|
|
1044
|
-
);
|
|
1045
|
-
|
|
1046
|
-
return txHash;
|
|
1047
|
-
})
|
|
1048
|
-
);
|
|
1070
|
+
try {
|
|
1071
|
+
const getHeaders = (index: number): Record<string, string> => {
|
|
1072
|
+
if (Array.isArray(requestSource)) {
|
|
1073
|
+
if (requestSource.length === 0) {
|
|
1074
|
+
return {};
|
|
1075
|
+
}
|
|
1076
|
+
const headerIndex = index < requestSource.length ? index : 0;
|
|
1077
|
+
const req = requestSource[headerIndex];
|
|
1078
|
+
return req ? client.pickGasPayerHeaders(req) : {};
|
|
1079
|
+
}
|
|
1049
1080
|
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
address: await getCustomerStakeAddress(userDid, nonce || subscriptionId || ''),
|
|
1057
|
-
},
|
|
1058
|
-
stakingAmount,
|
|
1059
|
-
};
|
|
1060
|
-
} catch (err) {
|
|
1061
|
-
logger.error('executeOcapTransactions failed', err);
|
|
1062
|
-
throw err;
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1081
|
+
if (requestSource && typeof requestSource === 'object') {
|
|
1082
|
+
return client.pickGasPayerHeaders(requestSource);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
return {};
|
|
1086
|
+
};
|
|
1065
1087
|
|
|
1088
|
+
const [delegationTxHash, stakingTxHash] = await Promise.all(
|
|
1089
|
+
transactions.map(async ([claim, type], index) => {
|
|
1090
|
+
if (!claim) {
|
|
1091
|
+
return '';
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
const tx: Partial<Transaction> = client.decodeTx(claim.finalTx || claim.origin);
|
|
1095
|
+
if (claim.sig) {
|
|
1096
|
+
tx.signature = claim.sig;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
// @ts-ignore
|
|
1100
|
+
const { buffer } = await client[`encode${type}Tx`]({ tx });
|
|
1101
|
+
const gasPayerHeaders = getHeaders(index);
|
|
1102
|
+
// @ts-ignore
|
|
1103
|
+
const txHash = await client[`send${type}Tx`](
|
|
1104
|
+
// @ts-ignore
|
|
1105
|
+
{ tx, wallet: fromPublicKey(userPk, toTypeInfo(userDid)) },
|
|
1106
|
+
getGasPayerExtra(buffer, gasPayerHeaders)
|
|
1107
|
+
);
|
|
1108
|
+
|
|
1109
|
+
return txHash;
|
|
1110
|
+
})
|
|
1111
|
+
);
|
|
1112
|
+
|
|
1113
|
+
return {
|
|
1114
|
+
tx_hash: delegationTxHash,
|
|
1115
|
+
payer: userDid,
|
|
1116
|
+
type: 'delegate',
|
|
1117
|
+
staking: {
|
|
1118
|
+
tx_hash: stakingTxHash,
|
|
1119
|
+
address: await getCustomerStakeAddress(userDid, nonce || subscriptionId || ''),
|
|
1120
|
+
},
|
|
1121
|
+
stakingAmount,
|
|
1122
|
+
};
|
|
1123
|
+
} catch (err) {
|
|
1124
|
+
logger.error('executeOcapTransactions failed', err);
|
|
1125
|
+
throw err;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1066
1128
|
|
|
1067
1129
|
export async function updateStripeSubscriptionAfterChangePayment(setupIntent: SetupIntent, subscription: Subscription) {
|
|
1068
1130
|
const { from_method: fromMethodId, to_method: toMethodId } = setupIntent.metadata || {};
|
|
@@ -129,6 +129,9 @@ export default {
|
|
|
129
129
|
result.push({
|
|
130
130
|
step,
|
|
131
131
|
claim: claims?.[0],
|
|
132
|
+
stepRequest: {
|
|
133
|
+
headers: request?.headers,
|
|
134
|
+
},
|
|
132
135
|
});
|
|
133
136
|
const staking = result.find((x: any) => x.claim?.type === 'prepareTx' && x.claim?.meta?.purpose === 'staking');
|
|
134
137
|
const isFinalStep = (paymentMethod.type === 'arcblock' && staking) || paymentMethod.type !== 'arcblock';
|
|
@@ -183,12 +186,19 @@ export default {
|
|
|
183
186
|
if (invoice) {
|
|
184
187
|
await invoice.update({ payment_settings: paymentSettings });
|
|
185
188
|
}
|
|
189
|
+
|
|
190
|
+
const requestArray = result
|
|
191
|
+
.map((item: { stepRequest?: Request }) => item.stepRequest)
|
|
192
|
+
.filter(Boolean) as Request[];
|
|
193
|
+
|
|
194
|
+
const requestSource = requestArray.length > 0 ? requestArray : request;
|
|
195
|
+
|
|
186
196
|
const { stakingAmount, ...paymentDetails } = await executeOcapTransactions(
|
|
187
197
|
userDid,
|
|
188
198
|
userPk,
|
|
189
199
|
claimsList,
|
|
190
200
|
paymentMethod,
|
|
191
|
-
|
|
201
|
+
requestSource,
|
|
192
202
|
subscription?.id,
|
|
193
203
|
paymentCurrency?.contract
|
|
194
204
|
);
|