Skip to content

Commit 913a852

Browse files
committed
Add EdgeAsset info for bitrefill
1 parent 2281e89 commit 913a852

File tree

1 file changed

+193
-49
lines changed

1 file changed

+193
-49
lines changed

src/partners/bitrefill.ts

Lines changed: 193 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,174 @@
1-
import { div } from 'biggystring'
21
import {
32
asArray,
43
asBoolean,
54
asNumber,
65
asObject,
76
asOptional,
87
asString,
9-
asUnknown
8+
asUnknown,
9+
asValue
1010
} from 'cleaners'
1111
import fetch from 'node-fetch'
1212

13-
import { PartnerPlugin, PluginParams, PluginResult, StandardTx } from '../types'
14-
import { safeParseFloat } from '../util'
13+
import {
14+
PartnerPlugin,
15+
PluginParams,
16+
PluginResult,
17+
StandardTx,
18+
Status
19+
} from '../types'
20+
import { smartIsoDateFromTimestamp } from '../util'
21+
import { EdgeTokenId } from '../util/asEdgeTokenId'
22+
import { EVM_CHAIN_IDS } from '../util/chainIds'
23+
24+
const asBitrefillStatus = asValue(
25+
'unpaid',
26+
'delivered',
27+
'sealed',
28+
'created',
29+
'permanent_failure',
30+
'refunded'
31+
)
1532

1633
const asBitrefillTx = asObject({
34+
status: asBitrefillStatus,
1735
paymentReceived: asBoolean,
1836
expired: asBoolean,
1937
sent: asBoolean,
2038
invoiceTime: asNumber,
21-
satoshiPrice: asOptional(asNumber),
39+
btcPrice: asString,
40+
altcoinPrice: asOptional(asString),
2241
value: asString,
2342
currency: asString,
2443
country: asString,
2544
coinCurrency: asString,
26-
receivedPaymentAltcoin: asOptional(asNumber),
45+
paymentMethod: asString,
46+
// receivedPaymentAltcoin: asOptional(asNumber),
2747
orderId: asString,
2848
usdPrice: asNumber
2949
})
3050

31-
// Partial type for Bitrefill txs for pre-processing
32-
const asPreBitrefillTx = asObject({
33-
expired: asBoolean,
34-
paymentReceived: asBoolean,
35-
sent: asBoolean,
36-
status: asString
37-
})
51+
type BitrefillTx = ReturnType<typeof asBitrefillTx>
52+
type BitrefillStatus = ReturnType<typeof asBitrefillStatus>
53+
const statusMap: { [key in BitrefillStatus]: Status } = {
54+
unpaid: 'pending',
55+
created: 'pending',
56+
delivered: 'complete',
57+
refunded: 'refunded',
58+
permanent_failure: 'failed',
59+
sealed: 'complete'
60+
}
3861

3962
const asBitrefillResult = asObject({
4063
nextUrl: asOptional(asString),
4164
orders: asArray(asUnknown)
4265
})
4366

44-
const multipliers: { [key: string]: string } = {
45-
BTC: '100000000',
46-
ETH: '1000000',
47-
LTC: '100000000',
48-
DASH: '100000000',
49-
DOGE: '100000000'
67+
const countryCodeMap: { [key: string]: string | null } = {
68+
argentina: 'AR',
69+
australia: 'AU',
70+
austria: 'AT',
71+
bangladesh: 'BD',
72+
belgium: 'BE',
73+
bolivia: 'BO',
74+
brazil: 'BR',
75+
canada: 'CA',
76+
chile: 'CL',
77+
china: 'CN',
78+
colombia: 'CO',
79+
'costa-rica': 'CR',
80+
'czech-republic': 'CZ',
81+
denmark: 'DK',
82+
'dominican-republic': 'DO',
83+
ecuador: 'EC',
84+
egypt: 'EG',
85+
'el-salvador': 'SV',
86+
finland: 'FI',
87+
france: 'FR',
88+
germany: 'DE',
89+
ghana: 'GH',
90+
greece: 'GR',
91+
guatemala: 'GT',
92+
honduras: 'HN',
93+
'hong-kong': 'HK',
94+
hungary: 'HU',
95+
india: 'IN',
96+
indonesia: 'ID',
97+
ireland: 'IE',
98+
israel: 'IL',
99+
italy: 'IT',
100+
japan: 'JP',
101+
kenya: 'KE',
102+
malaysia: 'MY',
103+
mexico: 'MX',
104+
morocco: 'MA',
105+
netherlands: 'NL',
106+
'new-zealand': 'NZ',
107+
nicaragua: 'NI',
108+
nigeria: 'NG',
109+
norway: 'NO',
110+
pakistan: 'PK',
111+
panama: 'PA',
112+
paraguay: 'PY',
113+
peru: 'PE',
114+
philippines: 'PH',
115+
poland: 'PL',
116+
portugal: 'PT',
117+
romania: 'RO',
118+
russia: 'RU',
119+
'saudi-arabia': 'SA',
120+
singapore: 'SG',
121+
'south-africa': 'ZA',
122+
'south-korea': 'KR',
123+
spain: 'ES',
124+
sweden: 'SE',
125+
switzerland: 'CH',
126+
taiwan: 'TW',
127+
thailand: 'TH',
128+
turkey: 'TR',
129+
ukraine: 'UA',
130+
'united-arab-emirates': 'AE',
131+
'united-kingdom': 'GB',
132+
uruguay: 'UY',
133+
usa: 'US',
134+
venezuela: 'VE',
135+
vietnam: 'VN',
136+
eu: 'EU',
137+
international: null
138+
}
139+
140+
const paymentMethodMap: {
141+
[key: string]: {
142+
pluginId: string
143+
tokenId: EdgeTokenId
144+
currencyCode: string
145+
}
146+
} = {
147+
bitcoin: { pluginId: 'bitcoin', tokenId: null, currencyCode: 'BTC' },
148+
dash: { pluginId: 'dash', tokenId: null, currencyCode: 'DASH' },
149+
ethereum: { pluginId: 'ethereum', tokenId: null, currencyCode: 'ETH' },
150+
litecoin: { pluginId: 'litecoin', tokenId: null, currencyCode: 'LTC' },
151+
dogecoin: { pluginId: 'dogecoin', tokenId: null, currencyCode: 'DOGE' },
152+
usdc_erc20: {
153+
pluginId: 'ethereum',
154+
tokenId: 'a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
155+
currencyCode: 'USDC'
156+
},
157+
usdc_polygon: {
158+
pluginId: 'polygon',
159+
tokenId: '3c499c542cef5e3811e1192ce70d8cc03d5c3359',
160+
currencyCode: 'USDC'
161+
},
162+
usdt_erc20: {
163+
pluginId: 'ethereum',
164+
tokenId: 'dac17f958d2ee523a2206206994597c13d831ec7',
165+
currencyCode: 'USDT'
166+
},
167+
usdt_trc20: {
168+
pluginId: 'tron',
169+
tokenId: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
170+
currencyCode: 'USDT'
171+
}
50172
}
51173

52174
export async function queryBitrefill(
@@ -74,7 +196,7 @@ export async function queryBitrefill(
74196
}
75197
const standardTxs: StandardTx[] = []
76198

77-
let url = `https://api.bitrefill.com/v1/orders/`
199+
let url = `https://api.bitrefill.com/v1/orders/?limit=150`
78200
let count = 0
79201
while (true) {
80202
let jsonObj: ReturnType<typeof asBitrefillResult>
@@ -83,22 +205,16 @@ export async function queryBitrefill(
83205
method: 'GET',
84206
headers
85207
})
86-
jsonObj = asBitrefillResult(await result.json())
208+
const json = await result.json()
209+
jsonObj = asBitrefillResult(json)
87210
} catch (e) {
88211
log.error(String(e))
89212
break
90213
}
91214
const txs = jsonObj.orders
92215
for (const rawTx of txs) {
93-
// Pre-process the tx to see if it's meets criteria for inclusion:
94-
const preTx = asPreBitrefillTx(rawTx)
95-
if (preTx.status === 'unpaid') {
96-
continue
97-
}
98-
if (preTx.paymentReceived && !preTx.expired && preTx.sent) {
99-
const standardTx = processBitrefillTx(rawTx)
100-
standardTxs.push(standardTx)
101-
}
216+
const standardTx = processBitrefillTx(rawTx, pluginParams)
217+
standardTxs.push(standardTx)
102218
}
103219

104220
if (count > MAX_ITERATIONS) {
@@ -127,34 +243,62 @@ export const bitrefill: PartnerPlugin = {
127243
pluginId: 'bitrefill'
128244
}
129245

130-
export function processBitrefillTx(rawTx: unknown): StandardTx {
131-
const tx = asBitrefillTx(rawTx)
132-
const timestamp = tx.invoiceTime / 1000
246+
export function processBitrefillTx(
247+
rawTx: unknown,
248+
pluginParams: PluginParams
249+
): StandardTx {
250+
const { log } = pluginParams
251+
let tx: BitrefillTx
252+
try {
253+
tx = asBitrefillTx(rawTx)
254+
} catch (e) {
255+
throw new Error(`${String(e)}: ${JSON.stringify(rawTx)}`)
256+
}
257+
const { isoDate } = smartIsoDateFromTimestamp(tx.invoiceTime)
258+
const countryCode = countryCodeMap[tx.country]
133259

134-
const inputCurrency: string = tx.coinCurrency.toUpperCase()
135-
if (typeof multipliers[inputCurrency] !== 'string') {
136-
throw new Error(inputCurrency + ' has no multipliers')
260+
if (tx.altcoinPrice != null) {
261+
log(
262+
`${tx.orderId}: ${isoDate} ${countryCode} ${tx.status} ${tx.paymentMethod} alt:${tx.altcoinPrice}`
263+
)
264+
} else {
265+
log(
266+
`${tx.orderId}: ${isoDate} ${countryCode} ${tx.status} ${tx.paymentMethod} btc:${tx.btcPrice}`
267+
)
137268
}
138-
let depositAmountStr = tx.satoshiPrice?.toString()
139-
if (typeof inputCurrency === 'string' && inputCurrency !== 'BTC') {
140-
depositAmountStr = tx.receivedPaymentAltcoin?.toString()
269+
const edgeAsset = paymentMethodMap[tx.paymentMethod]
270+
271+
if (edgeAsset == null) {
272+
throw new Error(`${tx.orderId}: ${tx.paymentMethod} has no payment method`)
273+
}
274+
if (countryCode === undefined) {
275+
throw new Error(`${tx.orderId}: ${tx.country} has no country code`)
276+
}
277+
const evmChainId = EVM_CHAIN_IDS[edgeAsset.pluginId]
278+
279+
const timestamp = tx.invoiceTime / 1000
280+
281+
const { paymentMethod } = tx
282+
let depositAmountStr: string | undefined
283+
if (paymentMethod === 'bitcoin') {
284+
depositAmountStr = tx.btcPrice
285+
} else if (tx.altcoinPrice != null) {
286+
depositAmountStr = tx.altcoinPrice
141287
}
142288
if (depositAmountStr == null) {
143289
throw new Error(`Missing depositAmount for tx: ${tx.orderId}`)
144290
}
145-
const depositAmount = safeParseFloat(
146-
div(depositAmountStr, multipliers[inputCurrency], 8)
147-
)
291+
const depositAmount = Number(depositAmountStr)
148292
const standardTx: StandardTx = {
149-
status: 'complete',
293+
status: statusMap[tx.status],
150294
orderId: tx.orderId,
151-
countryCode: tx.country.toUpperCase(),
295+
countryCode,
152296
depositTxid: undefined,
153297
depositAddress: undefined,
154-
depositCurrency: inputCurrency,
155-
depositChainPluginId: undefined,
156-
depositEvmChainId: undefined,
157-
depositTokenId: undefined,
298+
depositCurrency: edgeAsset.currencyCode,
299+
depositChainPluginId: edgeAsset.pluginId,
300+
depositEvmChainId: evmChainId,
301+
depositTokenId: edgeAsset.tokenId,
158302
depositAmount,
159303
direction: 'sell',
160304
exchangeType: 'fiat',
@@ -167,7 +311,7 @@ export function processBitrefillTx(rawTx: unknown): StandardTx {
167311
payoutTokenId: undefined,
168312
payoutAmount: parseInt(tx.value),
169313
timestamp,
170-
isoDate: new Date(tx.invoiceTime).toISOString(),
314+
isoDate,
171315
usdValue: tx.usdPrice,
172316
rawTx
173317
}

0 commit comments

Comments
 (0)