payment-kit 1.14.37 → 1.14.38
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/integrations/arcblock/stake.ts +1 -0
- package/api/src/libs/subscription.ts +23 -5
- package/api/src/libs/util.ts +12 -0
- package/api/src/queues/payment.ts +3 -3
- package/api/src/queues/refund.ts +5 -4
- package/api/src/queues/subscription.ts +4 -4
- package/api/src/routes/connect/shared.ts +4 -4
- package/blocklet.yml +1 -1
- package/package.json +4 -4
|
@@ -189,6 +189,7 @@ export async function getStakeSummaryByDid(did: string, livemode: boolean = true
|
|
|
189
189
|
return {};
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
+
// FIXME: should use listStakes to find all stakes and summarize here
|
|
192
193
|
const address = toStakeAddress(did, wallet.address);
|
|
193
194
|
const results: GroupedBN = {};
|
|
194
195
|
await Promise.all(
|
|
@@ -30,7 +30,7 @@ import dayjs from './dayjs';
|
|
|
30
30
|
import env from './env';
|
|
31
31
|
import logger from './logger';
|
|
32
32
|
import { getPriceCurrencyOptions, getPriceUintAmountByCurrency, getRecurringPeriod } from './session';
|
|
33
|
-
import { getConnectQueryParam } from './util';
|
|
33
|
+
import { getConnectQueryParam, getCustomerStakeAddress } from './util';
|
|
34
34
|
|
|
35
35
|
export function getCustomerSubscriptionPageUrl({
|
|
36
36
|
subscriptionId,
|
|
@@ -700,16 +700,25 @@ export async function getSubscriptionRemainingStakeSetup(
|
|
|
700
700
|
paymentMethod: PaymentMethod,
|
|
701
701
|
action: 'return' | 'slash' = 'return'
|
|
702
702
|
) {
|
|
703
|
+
const currency = await PaymentCurrency.findByPk(subscription.currency_id);
|
|
704
|
+
if (!currency) {
|
|
705
|
+
return {
|
|
706
|
+
total: '0',
|
|
707
|
+
return_amount: '0',
|
|
708
|
+
sender: '',
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
|
|
703
712
|
const client = paymentMethod.getOcapClient();
|
|
704
713
|
const { state } = await client.getStakeState({ address });
|
|
705
|
-
|
|
706
|
-
if (!state.tokens || !currency) {
|
|
714
|
+
if (!state) {
|
|
707
715
|
return {
|
|
708
716
|
total: '0',
|
|
709
717
|
return_amount: '0',
|
|
710
718
|
sender: '',
|
|
711
719
|
};
|
|
712
720
|
}
|
|
721
|
+
|
|
713
722
|
let total = new BN(state.tokens.find((x: any) => x.address === currency.contract)?.value || '0');
|
|
714
723
|
if (action === 'slash') {
|
|
715
724
|
// add revoked tokens to total
|
|
@@ -763,17 +772,18 @@ export async function checkRemainingStake(
|
|
|
763
772
|
revoked: '0',
|
|
764
773
|
};
|
|
765
774
|
}
|
|
775
|
+
|
|
766
776
|
const client = paymentMethod.getOcapClient();
|
|
767
777
|
const { state } = await client.getStakeState({ address });
|
|
768
|
-
|
|
769
778
|
if (!state) {
|
|
770
|
-
logger.warn('getStakeState failed in checkRemainingStake', { address
|
|
779
|
+
logger.warn('getStakeState failed in checkRemainingStake', { address });
|
|
771
780
|
return {
|
|
772
781
|
enough: false,
|
|
773
782
|
staked: '0',
|
|
774
783
|
revoked: '0',
|
|
775
784
|
};
|
|
776
785
|
}
|
|
786
|
+
|
|
777
787
|
const staked = state.tokens?.find((x: any) => x.address === paymentCurrency.contract);
|
|
778
788
|
const revoked = state.revokedTokens?.find((x: any) => x.address === paymentCurrency.contract);
|
|
779
789
|
let total = new BN(0);
|
|
@@ -783,6 +793,7 @@ export async function checkRemainingStake(
|
|
|
783
793
|
if (revoked) {
|
|
784
794
|
total = total.add(new BN(revoked?.value || '0'));
|
|
785
795
|
}
|
|
796
|
+
|
|
786
797
|
return {
|
|
787
798
|
enough: total.gte(new BN(amount)),
|
|
788
799
|
staked,
|
|
@@ -805,3 +816,10 @@ export function getSubscriptionTrialSetup(data: Partial<SubscriptionData>, curre
|
|
|
805
816
|
trialEnd,
|
|
806
817
|
};
|
|
807
818
|
}
|
|
819
|
+
|
|
820
|
+
export async function getSubscriptionStakeAddress(subscription: Subscription, customerDid: string) {
|
|
821
|
+
return (
|
|
822
|
+
subscription.payment_details?.arcblock?.staking?.address ||
|
|
823
|
+
(await getCustomerStakeAddress(customerDid, subscription.id))
|
|
824
|
+
);
|
|
825
|
+
}
|
package/api/src/libs/util.ts
CHANGED
|
@@ -2,11 +2,14 @@ import crypto from 'crypto';
|
|
|
2
2
|
|
|
3
3
|
import { getUrl } from '@blocklet/sdk/lib/component';
|
|
4
4
|
import env from '@blocklet/sdk/lib/env';
|
|
5
|
+
import { getWalletDid } from '@blocklet/sdk/lib/did';
|
|
6
|
+
import { toStakeAddress } from '@arcblock/did-util';
|
|
5
7
|
import { customAlphabet } from 'nanoid';
|
|
6
8
|
import type { LiteralUnion } from 'type-fest';
|
|
7
9
|
import { withQuery } from 'ufo';
|
|
8
10
|
|
|
9
11
|
import dayjs from './dayjs';
|
|
12
|
+
import { blocklet, wallet } from './auth';
|
|
10
13
|
|
|
11
14
|
export const OCAP_PAYMENT_TX_TYPE = 'fg:t:transfer_v2';
|
|
12
15
|
|
|
@@ -260,3 +263,12 @@ export function formatAmountPrecisionLimit(
|
|
|
260
263
|
}
|
|
261
264
|
return '';
|
|
262
265
|
}
|
|
266
|
+
|
|
267
|
+
export async function getCustomerStakeAddress(customerDid: string, nonce?: string) {
|
|
268
|
+
const { user } = await blocklet.getUser(customerDid, { enableConnectedAccount: true });
|
|
269
|
+
if (user) {
|
|
270
|
+
return toStakeAddress(getWalletDid(user), wallet.address, nonce);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return toStakeAddress(customerDid, wallet.address, nonce);
|
|
274
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import isEmpty from 'lodash/isEmpty';
|
|
2
2
|
|
|
3
|
-
import { toStakeAddress } from '@arcblock/did-util';
|
|
4
3
|
import { ensureStakedForGas } from '../integrations/arcblock/stake';
|
|
5
4
|
import { transferErc20FromUser } from '../integrations/ethereum/token';
|
|
6
5
|
import { createEvent } from '../libs/audit';
|
|
@@ -19,6 +18,7 @@ import {
|
|
|
19
18
|
getMaxRetryCount,
|
|
20
19
|
getMinRetryMail,
|
|
21
20
|
getSubscriptionCreateSetup,
|
|
21
|
+
getSubscriptionStakeAddress,
|
|
22
22
|
shouldCancelSubscription,
|
|
23
23
|
} from '../libs/subscription';
|
|
24
24
|
import { MAX_RETRY_COUNT, MIN_RETRY_MAIL, getNextRetry } from '../libs/util';
|
|
@@ -402,7 +402,7 @@ const handleStakeSlash = async (
|
|
|
402
402
|
return;
|
|
403
403
|
}
|
|
404
404
|
|
|
405
|
-
const address =
|
|
405
|
+
const address = await getSubscriptionStakeAddress(subscription, customer.did);
|
|
406
406
|
const slashAmount = paymentIntent.amount;
|
|
407
407
|
const stakeEnough = await checkRemainingStake(paymentMethod, paymentCurrency, address, slashAmount);
|
|
408
408
|
if (!stakeEnough.enough) {
|
|
@@ -432,7 +432,7 @@ const handleStakeSlash = async (
|
|
|
432
432
|
const signed = await client.signSlashStakeTx({
|
|
433
433
|
tx: {
|
|
434
434
|
itx: {
|
|
435
|
-
address
|
|
435
|
+
address,
|
|
436
436
|
outputs: [{ owner: wallet.address, tokens: [{ address: paymentCurrency.contract, value: slashAmount }] }],
|
|
437
437
|
message: 'stake_slash_on_subscription_cancel',
|
|
438
438
|
data: {
|
package/api/src/queues/refund.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { checkRemainingStake } from '@api/libs/subscription';
|
|
1
|
+
import { isRefundReasonSupportedByStripe } from '../libs/refund';
|
|
2
|
+
import { checkRemainingStake, getSubscriptionStakeAddress } from '../libs/subscription';
|
|
4
3
|
import { sendErc20ToUser } from '../integrations/ethereum/token';
|
|
5
4
|
import { wallet } from '../libs/auth';
|
|
6
5
|
import CustomError from '../libs/error';
|
|
@@ -14,6 +13,7 @@ import { PaymentCurrency } from '../store/models/payment-currency';
|
|
|
14
13
|
import { PaymentIntent } from '../store/models/payment-intent';
|
|
15
14
|
import { PaymentMethod } from '../store/models/payment-method';
|
|
16
15
|
import { Refund } from '../store/models/refund';
|
|
16
|
+
import { Subscription } from '../store/models/subscription';
|
|
17
17
|
import type { PaymentError } from '../store/models/types';
|
|
18
18
|
|
|
19
19
|
type RefundJob = {
|
|
@@ -313,7 +313,8 @@ const handleStakeReturnJob = async (
|
|
|
313
313
|
return;
|
|
314
314
|
}
|
|
315
315
|
const client = paymentMethod.getOcapClient();
|
|
316
|
-
const
|
|
316
|
+
const subscription = await Subscription.findByPk(refund.subscription_id);
|
|
317
|
+
const address = await getSubscriptionStakeAddress(subscription!, customer.did);
|
|
317
318
|
const stakeEnough = await checkRemainingStake(paymentMethod, paymentCurrency, address, refund.amount);
|
|
318
319
|
if (!stakeEnough.enough) {
|
|
319
320
|
logger.warn('Stake return aborted because stake is not enough ', {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { toStakeAddress } from '@arcblock/did-util';
|
|
2
1
|
import type { LiteralUnion } from 'type-fest';
|
|
3
2
|
|
|
4
3
|
import { ensurePassportRevoked } from '../integrations/blocklet/passport';
|
|
@@ -15,6 +14,7 @@ import {
|
|
|
15
14
|
checkRemainingStake,
|
|
16
15
|
getSubscriptionCycleAmount,
|
|
17
16
|
getSubscriptionCycleSetup,
|
|
17
|
+
getSubscriptionStakeAddress,
|
|
18
18
|
getSubscriptionStakeReturnSetup,
|
|
19
19
|
getSubscriptionStakeSlashSetup,
|
|
20
20
|
shouldCancelSubscription,
|
|
@@ -329,7 +329,7 @@ const handleStakeSlashAfterCancel = async (subscription: Subscription) => {
|
|
|
329
329
|
|
|
330
330
|
// check the staking
|
|
331
331
|
const client = method.getOcapClient();
|
|
332
|
-
const address =
|
|
332
|
+
const address = await getSubscriptionStakeAddress(subscription, customer.did);
|
|
333
333
|
const { state } = await client.getStakeState({ address });
|
|
334
334
|
if (!state || !state.data?.value) {
|
|
335
335
|
logger.warn('Stake slashing aborted because no staking state', {
|
|
@@ -374,7 +374,7 @@ const handleStakeSlashAfterCancel = async (subscription: Subscription) => {
|
|
|
374
374
|
const signed = await client.signSlashStakeTx({
|
|
375
375
|
tx: {
|
|
376
376
|
itx: {
|
|
377
|
-
address
|
|
377
|
+
address,
|
|
378
378
|
outputs: [{ owner: wallet.address, tokens: [{ address: currency.contract, value: invoice.amount_remaining }] }],
|
|
379
379
|
message: 'uncollectible_past_due_invoice',
|
|
380
380
|
data: {
|
|
@@ -530,7 +530,6 @@ const slashStakeOnCancel = async (subscription: Subscription) => {
|
|
|
530
530
|
});
|
|
531
531
|
return;
|
|
532
532
|
}
|
|
533
|
-
const address = toStakeAddress(customer.did, wallet.address, subscription.id);
|
|
534
533
|
const currency = await PaymentCurrency.findByPk(subscription.currency_id);
|
|
535
534
|
if (!currency) {
|
|
536
535
|
logger.warn('Stake slashing skipped because currency not found', {
|
|
@@ -539,6 +538,7 @@ const slashStakeOnCancel = async (subscription: Subscription) => {
|
|
|
539
538
|
});
|
|
540
539
|
return;
|
|
541
540
|
}
|
|
541
|
+
const address = await getSubscriptionStakeAddress(subscription, customer.did);
|
|
542
542
|
const result = await getSubscriptionStakeSlashSetup(subscription, address, paymentMethod);
|
|
543
543
|
const stakeEnough = await checkRemainingStake(paymentMethod, currency, address, result.return_amount);
|
|
544
544
|
if (!stakeEnough.enough) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/indent */
|
|
2
2
|
/* eslint-disable prettier/prettier */
|
|
3
3
|
import { toTypeInfo } from '@arcblock/did';
|
|
4
|
-
import { toDelegateAddress
|
|
4
|
+
import { toDelegateAddress } from '@arcblock/did-util';
|
|
5
5
|
import type { Transaction } from '@ocap/client';
|
|
6
6
|
import { BN, fromTokenToUnit, toBase58 } from '@ocap/util';
|
|
7
7
|
import { fromPublicKey } from '@ocap/wallet';
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
getSubscriptionItemPrice,
|
|
22
22
|
getSubscriptionStakeSetup,
|
|
23
23
|
} from '../../libs/subscription';
|
|
24
|
-
import { OCAP_PAYMENT_TX_TYPE } from '../../libs/util';
|
|
24
|
+
import { getCustomerStakeAddress, OCAP_PAYMENT_TX_TYPE } from '../../libs/util';
|
|
25
25
|
import { invoiceQueue } from '../../queues/invoice';
|
|
26
26
|
import type { TLineItemExpanded } from '../../store/models';
|
|
27
27
|
import { CheckoutSession } from '../../store/models/checkout-session';
|
|
@@ -745,7 +745,7 @@ export async function getStakeTxClaim({
|
|
|
745
745
|
if (paymentMethod.type === 'arcblock') {
|
|
746
746
|
// create staking data
|
|
747
747
|
const client = paymentMethod.getOcapClient();
|
|
748
|
-
const address =
|
|
748
|
+
const address = await getCustomerStakeAddress(userDid, subscription.id);
|
|
749
749
|
const { state } = await client.getStakeState({ address });
|
|
750
750
|
const data = {
|
|
751
751
|
type: 'json',
|
|
@@ -1026,7 +1026,7 @@ export async function executeOcapTransactions(
|
|
|
1026
1026
|
type: 'delegate',
|
|
1027
1027
|
staking: {
|
|
1028
1028
|
tx_hash: stakingTxHash,
|
|
1029
|
-
address:
|
|
1029
|
+
address: await getCustomerStakeAddress(userDid, nonce),
|
|
1030
1030
|
},
|
|
1031
1031
|
};
|
|
1032
1032
|
}
|
package/blocklet.yml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.38",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "blocklet dev --open",
|
|
6
6
|
"eject": "vite eject",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"@arcblock/validator": "^1.18.132",
|
|
53
53
|
"@blocklet/js-sdk": "1.16.30",
|
|
54
54
|
"@blocklet/logger": "1.16.30",
|
|
55
|
-
"@blocklet/payment-react": "1.14.
|
|
55
|
+
"@blocklet/payment-react": "1.14.38",
|
|
56
56
|
"@blocklet/sdk": "1.16.30",
|
|
57
57
|
"@blocklet/ui-react": "^2.10.23",
|
|
58
58
|
"@blocklet/uploader": "^0.1.27",
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"devDependencies": {
|
|
120
120
|
"@abtnode/types": "1.16.30",
|
|
121
121
|
"@arcblock/eslint-config-ts": "^0.3.2",
|
|
122
|
-
"@blocklet/payment-types": "1.14.
|
|
122
|
+
"@blocklet/payment-types": "1.14.38",
|
|
123
123
|
"@types/cookie-parser": "^1.4.7",
|
|
124
124
|
"@types/cors": "^2.8.17",
|
|
125
125
|
"@types/debug": "^4.1.12",
|
|
@@ -161,5 +161,5 @@
|
|
|
161
161
|
"parser": "typescript"
|
|
162
162
|
}
|
|
163
163
|
},
|
|
164
|
-
"gitHead": "
|
|
164
|
+
"gitHead": "f572122a40f30619bd736d8df20e362b6cdab420"
|
|
165
165
|
}
|