Skip to content

Commit

Permalink
Add network optional parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
RashadAnsari committed Jul 17, 2023
1 parent 2519544 commit b2cd32f
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 42 deletions.
17 changes: 17 additions & 0 deletions docs/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ paths:
schema:
type: string
example: BTC
- name: network
in: query
required: false
schema:
type: string
example: Bitcoin
- name: transactionId
in: path
required: true
Expand Down Expand Up @@ -103,6 +109,12 @@ paths:
schema:
type: string
example: ETH
- name: network
in: query
required: false
schema:
type: string
example: Ethereum
- name: walletId
in: path
required: true
Expand Down Expand Up @@ -146,6 +158,9 @@ components:
symbol:
type: string
example: BTC
network:
type: string
example: Bitcoin
accountIndex:
type: integer
format: int64
Expand All @@ -164,6 +179,8 @@ components:
default: 0
minimum: 0
example: 1
required:
- symbol
CreateHDWalletResponse:
type: object
properties:
Expand Down
28 changes: 6 additions & 22 deletions src/cfg.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,10 @@ export const mnemonic = getEnv('MNEMONIC');
export const passphrase = getEnv('PASSPHRASE', '');
export const blockchairAPIKey = getEnv('BLOCKCHAIR_API_KEY', '');

export const cryptoChainIds = {
BTC: [0],
LTC: [2],
ETH: [60],
DOGE: [3],
ADA: [1815],
export const cryptoNetworks = {
BTC: ['Bitcoin'],
LTC: ['Litecoin'],
ETH: ['Ethereum'],
DOGE: ['Dogecoin'],
ADA: ['Cardano'],
};

export function symbolValidator(symbol, helpers) {
const cryptoSymbols = Object.keys(cryptoChainIds);

if (cryptoSymbols.includes(symbol.toUpperCase())) {
return symbol.toUpperCase();
}

return helpers.message(
'"symbol" must be one of [' + cryptoSymbols.join(', ') + ']',
);
}

export function getChainId(symbol) {
return cryptoChainIds[symbol.toUpperCase()][0];
}
14 changes: 10 additions & 4 deletions src/crypto/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,11 @@ const transactionInfoAPIs = {
},
};

export const getTransactionInfo = async (symbol, transactionId) => {
const apiDetails = transactionInfoAPIs[symbol];
export const getTransactionInfo = async (symbol, network, transactionId) => {
const apiDetails =
network && transactionInfoAPIs[symbol][network]
? transactionInfoAPIs[symbol][network]
: transactionInfoAPIs[symbol];

const txInfoResponse = await axios.get(
`${apiDetails.txInfoUrl.replace('<transactionId>', transactionId)}${
Expand Down Expand Up @@ -285,8 +288,11 @@ const walletInfoAPIs = {
},
};

export const getWalletInfo = async (symbol, walletId) => {
const apiDetails = walletInfoAPIs[symbol];
export const getWalletInfo = async (symbol, network, walletId) => {
const apiDetails =
network && walletInfoAPIs[symbol][network]
? walletInfoAPIs[symbol][network]
: walletInfoAPIs[symbol];

const walletResponse = await axios.get(
`${apiDetails.dataUrl.replace('<walletId>', walletId)}${
Expand Down
38 changes: 25 additions & 13 deletions src/routes/crypto.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import joi from 'joi';
import { Router } from 'express';
import { toHexString } from '../utils.js';
import { symbolValidator, mnemonic, passphrase, getChainId } from '../cfg.js';
import { mnemonic, passphrase } from '../cfg.js';
import { getTransactionInfo, getWalletInfo } from '../crypto/crypto.js';
import {
symbolValidator,
networkValidator,
getCoinType,
toHexString,
} from '../utils.js';

const router = Router();

const hdwalletPostSchema = joi.object({
symbol: joi.string().custom(symbolValidator).required(),
network: joi.string().custom(networkValidator),
accountIndex: joi.number().min(0).default(0),
externalChain: joi.number().min(0).default(0),
addressIndex: joi.number().min(0).default(0),
Expand All @@ -22,12 +28,11 @@ router.post('/v1/hdwallet', async (req, res, next) => {

/** @type {import('@trustwallet/wallet-core').WalletCore} */
const { HDWallet, AnyAddress } = req.app.locals.core;
const { symbol, accountIndex, externalChain, addressIndex } = value;
const { symbol, network, accountIndex, externalChain, addressIndex } = value;

try {
const hdwallet = HDWallet.createWithMnemonic(mnemonic, passphrase);
const chainId = getChainId(symbol);
const coinType = { value: chainId };
const coinType = getCoinType(symbol, network, req.app.locals.core);
const privateKey = hdwallet.getDerivedKey(
coinType,
accountIndex,
Expand Down Expand Up @@ -57,11 +62,15 @@ router.post('/v1/hdwallet', async (req, res, next) => {

const getTransactionSchema = joi.object({
symbol: joi.string().custom(symbolValidator).required(),
network: joi.string().custom(networkValidator),
transactionId: joi.string().required(),
});

router.get('/v1/:symbol/transaction/:transactionId', async (req, res, next) => {
const { value, error } = getTransactionSchema.validate(req.params);
const { value, error } = getTransactionSchema.validate({
...req.params,
...req.query,
});
if (error) {
const errorMessages = error.details.map((detail) => detail.message);
return res.status(400).json({ errors: errorMessages });
Expand All @@ -70,16 +79,15 @@ router.get('/v1/:symbol/transaction/:transactionId', async (req, res, next) => {
/** @type {import('@trustwallet/wallet-core').WalletCore} */
const core = req.app.locals.core;
const { CoinTypeConfiguration } = core;
const { symbol, transactionId } = value;
const { symbol, network, transactionId } = value;

try {
const chainId = getChainId(symbol);
const coinType = { value: chainId };
const coinType = getCoinType(symbol, network, req.app.locals.core);
const url = CoinTypeConfiguration.getTransactionURL(
coinType,
transactionId,
);
const info = await getTransactionInfo(symbol, transactionId);
const info = await getTransactionInfo(symbol, network, transactionId);

const response = { ...info, url };

Expand All @@ -91,20 +99,24 @@ router.get('/v1/:symbol/transaction/:transactionId', async (req, res, next) => {

const getWalletTransactionsSchema = joi.object({
symbol: joi.string().custom(symbolValidator).required(),
network: joi.string().custom(networkValidator),
walletId: joi.string().required(),
});

router.get('/v1/:symbol/wallet/:walletId', async (req, res, next) => {
const { value, error } = getWalletTransactionsSchema.validate(req.params);
const { value, error } = getWalletTransactionsSchema.validate({
...req.params,
...req.query,
});
if (error) {
const errorMessages = error.details.map((detail) => detail.message);
return res.status(400).json({ errors: errorMessages });
}

const { symbol, walletId } = value;
const { symbol, network, walletId } = value;

try {
const response = await getWalletInfo(symbol, walletId);
const response = await getWalletInfo(symbol, network, walletId);

res.json(response);
} catch (error) {
Expand Down
53 changes: 50 additions & 3 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,57 @@
import { cryptoNetworks } from './cfg.js';

export function symbolValidator(symbol, helpers) {
const cryptoSymbols = Object.keys(cryptoNetworks);

if (cryptoSymbols.includes(symbol.toUpperCase())) {
return symbol.toUpperCase();
}

return helpers.message(
'"symbol" must be one of [' + cryptoSymbols.join(', ') + ']',
);
}

export function networkValidator(network, helpers) {
const symbol = helpers.state.ancestors[0].symbol;
const cryptoSymbols = Object.keys(cryptoNetworks);

if (!cryptoSymbols.includes(symbol.toUpperCase())) {
return helpers.message(
'"symbol" must be one of [' + cryptoSymbols.join(', ') + ']',
);
}

const networks = cryptoNetworks[symbol.toUpperCase()];
for (const i in networks) {
if (networks[i].toLowerCase() === network.toLowerCase()) {
return networks[i];
}
}

return helpers.message(
'"network" must be one of [' + networks.join(', ') + ']',
);
}

export function getCoinType(symbol, network, walletCore) {
/** @type {import('@trustwallet/wallet-core').WalletCore} */
const { CoinType } = walletCore;

if (network) {
return CoinType[network.toLowerCase()];
}

const defaultNetwork = cryptoNetworks[symbol.toUpperCase()][0];
return CoinType[defaultNetwork.toLowerCase()];
}

export function toHexString(byteArray) {
return Array.from(byteArray, (byte) =>
`0${(byte & 0xff).toString(16)}`.slice(-2),
).join('');
}

export function toTimestamp(strDate) {
const dt = Date.parse(strDate);
return dt / 1000; // convert to seconds.
export function toTimestamp(date) {
return Date.parse(date) / 1000; // convert to seconds.
}

0 comments on commit b2cd32f

Please sign in to comment.