Skip to content

Commit 0027fa2

Browse files
author
xgram
committed
added: Xgram swap provider
1 parent dced8ba commit 0027fa2

File tree

5 files changed

+52
-76
lines changed

5 files changed

+52
-76
lines changed

scripts/mappings/xgramMappings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ xgram.set('AVAXC', 'avalanche')
2020
xgram.set('BITCOINCASH', 'bitcoincash')
2121

2222
// WARNING: Not included by the synchronizer synchronization
23-
xgram.set('BSC', 'binance')
23+
xgram.set('BSC', 'binancesmartchain')
2424

2525
// WARNING: Not included by the synchronizer synchronization
2626
xgram.set('BSV', 'bitcoinsv')
Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,17 @@
1-
import fs from 'fs'
2-
import path from 'path'
3-
4-
import { EdgeCurrencyPluginId } from '../../../src/util/edgeCurrencyPluginIds'
51
import { MapctlConfig } from '../../mapctlConfig'
62
import { FetchChainCodeResult, SwapSynchronizer } from '../../types'
3+
import { getMappingFilePath, loadMappingFile } from '../../util/loadMappingFile'
74

8-
const MAPPING_FILE_PATH = path.join(
9-
__dirname,
10-
'../../mappings/xgramMappings.ts'
11-
)
12-
5+
const NAME = 'xgram'
136
export const makeXgramSynchronizer = (
147
_config: MapctlConfig
158
): SwapSynchronizer => {
169
return {
17-
name: 'xgram',
18-
get map(): Map<string, EdgeCurrencyPluginId | null> {
19-
if (fs.existsSync(MAPPING_FILE_PATH)) {
20-
// eslint-disable-next-line @typescript-eslint/no-var-requires
21-
const { xgram } = require('../../mappings/xgramMappings')
22-
return xgram
23-
}
24-
return new Map()
10+
name: NAME,
11+
get map() {
12+
return loadMappingFile(NAME)
2513
},
26-
mappingFilePath: MAPPING_FILE_PATH,
27-
fetchChainCodes: async (): Promise<FetchChainCodeResult[]> => {
28-
return []
29-
}
14+
mappingFilePath: getMappingFilePath(NAME),
15+
fetchChainCodes: async (): Promise<FetchChainCodeResult[]> => []
3016
}
3117
}

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ const plugins = {
3232
bridgeless: makeBridgelessPlugin,
3333
changehero: makeChangeHeroPlugin,
3434
changenow: makeChangeNowPlugin,
35-
xgram: makeXgramPlugin,
3635
cosmosibc: makeCosmosIbcPlugin,
3736
exolix: makeExolixPlugin,
3837
godex: makeGodexPlugin,
@@ -50,6 +49,7 @@ const plugins = {
5049
transfer: makeTransferPlugin,
5150
unizen: makeUnizenPlugin,
5251
velodrome: makeVelodromePlugin,
52+
xgram: makeXgramPlugin,
5353
xrpdex,
5454
fantomsonicupgrade: makeFantomSonicUpgradePlugin,
5555
'0xgasless': make0xGaslessPlugin

src/mappings/xgram.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ xgram.set('avalanche', 'AVAXC')
2222
xgram.set('axelar', null)
2323
xgram.set('badcoin', null)
2424
xgram.set('base', null)
25-
xgram.set('binance', 'BSC')
26-
xgram.set('binancesmartchain', null)
25+
xgram.set('binance', null)
26+
xgram.set('binancesmartchain', 'BSC')
2727
xgram.set('bitcoin', 'BTC')
2828
xgram.set('bitcoincash', 'BITCOINCASH')
2929
xgram.set('bitcoincashtestnet', null)
@@ -34,6 +34,7 @@ xgram.set('bitcointestnet', null)
3434
xgram.set('bitcointestnet4', null)
3535
xgram.set('bobevm', null)
3636
xgram.set('botanix', null)
37+
xgram.set('cacao', null)
3738
xgram.set('calibration', null)
3839
xgram.set('cardano', 'ada')
3940
xgram.set('cardanotestnet', null)
@@ -63,7 +64,11 @@ xgram.set('hyperevm', null)
6364
xgram.set('liberland', null)
6465
xgram.set('liberlandtestnet', null)
6566
xgram.set('litecoin', null)
67+
xgram.set('mayachain', null)
68+
xgram.set('monad', null)
6669
xgram.set('monero', 'XMR')
70+
xgram.set('nym', null)
71+
xgram.set('opbnb', null)
6772
xgram.set('optimism', 'OPTIMISM')
6873
xgram.set('osmosis', 'OSMO')
6974
xgram.set('piratechain', null)

src/swap/central/xgram.ts

Lines changed: 36 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ import {
33
asBoolean,
44
asDate,
55
asEither,
6+
asMaybe,
67
asNumber,
78
asObject,
8-
asOptional,
99
asString,
10-
asValue,
11-
Cleaner
10+
asValue
1211
} from 'cleaners'
1312
import {
1413
EdgeCorePluginOptions,
@@ -29,17 +28,21 @@ import { EdgeCurrencyPluginId } from '../../util/edgeCurrencyPluginIds'
2928
import {
3029
checkWhitelistedMainnetCodes,
3130
CurrencyPluginIdSwapChainCodeMap,
32-
denominationToNative,
3331
ensureInFuture,
3432
getContractAddresses,
3533
getMaxSwappable,
3634
makeSwapPluginQuote,
3735
mapToRecord,
38-
nativeToDenomination,
3936
SwapOrder
4037
} from '../../util/swapHelpers'
41-
import { convertRequest, getAddress, memoType } from '../../util/utils'
42-
import { EdgeSwapRequestPlugin } from '../types'
38+
import {
39+
convertRequest,
40+
denominationToNative,
41+
getAddress,
42+
memoType,
43+
nativeToDenomination
44+
} from '../../util/utils'
45+
import { EdgeSwapRequestPlugin, StringMap } from '../types'
4346

4447
const pluginId = 'xgram'
4548

@@ -51,8 +54,7 @@ export const swapInfo: EdgeSwapInfo = {
5154
}
5255

5356
const asInitOptions = asObject({
54-
apiKey: asString,
55-
affiliateId: asOptional(asString)
57+
apiKey: asString
5658
})
5759

5860
const orderUri = 'https://xgram.io/exchange/order?id='
@@ -64,8 +66,11 @@ export const MAINNET_CODE_TRANSCRIPTION: CurrencyPluginIdSwapChainCodeMap = mapT
6466
xgramMapping
6567
)
6668

67-
const swapType: FlowType = 'fixed'
68-
type FlowType = 'fixed' | 'float'
69+
const addressTypeMap: StringMap = {
70+
zcash: 'transparentAddress'
71+
}
72+
73+
const swapType = 'fixed' as const
6974

7075
export function makeXgramPlugin(opts: EdgeCorePluginOptions): EdgeSwapPlugin {
7176
const { io } = opts
@@ -85,8 +90,14 @@ export function makeXgramPlugin(opts: EdgeCorePluginOptions): EdgeSwapPlugin {
8590
const { fromWallet, toWallet, nativeAmount } = request
8691

8792
const [fromAddress, toAddress] = await Promise.all([
88-
getAddress(fromWallet),
89-
getAddress(toWallet)
93+
getAddress(
94+
request.fromWallet,
95+
addressTypeMap[request.fromWallet.currencyInfo.pluginId]
96+
),
97+
getAddress(
98+
request.toWallet,
99+
addressTypeMap[request.toWallet.currencyInfo.pluginId]
100+
)
90101
])
91102

92103
const { fromContractAddress, toContractAddress } = getContractAddresses(
@@ -132,10 +143,11 @@ export function makeXgramPlugin(opts: EdgeCorePluginOptions): EdgeSwapPlugin {
132143

133144
const orderResponseJson = await orderResponse.json()
134145
const quoteFor = request?.quoteFor === 'from' ? 'from' : 'to'
135-
const quoteReply = asTemplateQuoteReply(orderResponseJson)
146+
const quoteReply = asXgramQuoteReply(orderResponseJson)
136147

137148
if ('errors' in quoteReply) {
138149
const errors = quoteReply.errors
150+
139151
if (errors.find(error => error.code === 'REGION_UNSUPPORTED') != null) {
140152
throw new SwapPermissionError(swapInfo, 'geoRestriction')
141153
}
@@ -145,7 +157,9 @@ export function makeXgramPlugin(opts: EdgeCorePluginOptions): EdgeSwapPlugin {
145157
) {
146158
throw new SwapCurrencyError(swapInfo, request)
147159
}
148-
const limitError = errors.find(isTemplateLimitError)
160+
const limitError = errors
161+
.map(e => asMaybe(asXgramLimitError)(e))
162+
.find(e => e != null)
149163

150164
if (limitError?.code === 'BELOW_LIMIT') {
151165
const sourceAmountLimit = denominationToNative(
@@ -297,15 +311,6 @@ export function makeXgramPlugin(opts: EdgeCorePluginOptions): EdgeSwapPlugin {
297311
return out
298312
}
299313

300-
export function asOptionalBlank<T>(
301-
cleaner: Cleaner<T>
302-
): Cleaner<T | undefined> {
303-
return function asIgnoredBlank(raw: any) {
304-
if (raw == null || raw === '') return undefined
305-
return cleaner(raw)
306-
}
307-
}
308-
309314
interface XgramResponse {
310315
id: string
311316
fromAmount: string
@@ -315,48 +320,28 @@ interface XgramResponse {
315320
validUntil?: Date | null
316321
}
317322

318-
// Type guard to narrow Xgram limit errors in the union type
319-
function isTemplateLimitError(
320-
error: any
321-
): error is {
322-
code: 'BELOW_LIMIT' | 'ABOVE_LIMIT'
323-
destinationAmountLimit: string
324-
error: string
325-
sourceAmountLimit: string
326-
} {
327-
return (
328-
error != null &&
329-
(error.code === 'BELOW_LIMIT' || error.code === 'ABOVE_LIMIT') &&
330-
typeof error.sourceAmountLimit === 'string'
331-
)
332-
}
333-
334-
const asTemplateLimitError = asObject({
323+
const asXgramLimitError = asObject({
335324
code: asValue('BELOW_LIMIT', 'ABOVE_LIMIT'),
336325
destinationAmountLimit: asString,
337326
error: asString,
338327
sourceAmountLimit: asString
339328
})
340329

341-
const asTemplateRegionError = asObject({
330+
const asXgramRegionError = asObject({
342331
code: asValue('REGION_UNSUPPORTED'),
343332
message: asString
344333
})
345334

346-
const asTemplateCurrencyError = asObject({
335+
const asXgramCurrencyError = asObject({
347336
code: asValue('CURRENCY_UNSUPPORTED'),
348337
error: asString
349338
})
350-
const asTemplateError = asObject({
339+
const asXgramError = asObject({
351340
errors: asArray(
352-
asEither(
353-
asTemplateLimitError,
354-
asTemplateRegionError,
355-
asTemplateCurrencyError
356-
)
341+
asEither(asXgramLimitError, asXgramRegionError, asXgramCurrencyError)
357342
)
358343
})
359-
const asTemplateQuote = asObject({
344+
const asXgramQuote = asObject({
360345
ccyAmountToExpected: asNumber,
361346
depositAddress: asString,
362347
depositTag: asString,
@@ -365,4 +350,4 @@ const asTemplateQuote = asObject({
365350
expiresAt: asDate,
366351
ccyAmountFrom: asString
367352
})
368-
const asTemplateQuoteReply = asEither(asTemplateQuote, asTemplateError)
353+
const asXgramQuoteReply = asEither(asXgramQuote, asXgramError)

0 commit comments

Comments
 (0)