@gateway.fm/gtw-dvf-client-js
Version:
DVF client js lib with gateway.fm rpc endpoints
101 lines (86 loc) • 3.07 kB
JavaScript
const {
Joi,
toQuantizedAmountBN
} = require('dvf-utils')
const validateWithJoi = require('../validators/validateWithJoi')
const DVFError = require('./DVFError')
const makeCreateSignedTransferTx = require('./makeCreateSignedTransferTx')
const getSafeQuantizedAmountOrThrow = require('./token/getSafeQuantizedAmountOrThrow')
const getValidTokenInfo = dvf => token => {
const tokenInfo = dvf.token.getTokenInfoOrThrow(token)
if (!tokenInfo.starkVaultId) {
throw new DVFError(
'NO_STARK_VAULT_ID_FOR_TOKEN',
{token, context: 'createTransferPayload'}
)
}
return tokenInfo
}
const transferDataSchema = Joi.object({
amount: Joi.amount(),
// NOTE: we are not specifying allowed tokens here since these can change
// dynamically. However a call to `getTokenInfoOrThrow` will ensure that
// the token in valid.
memo: Joi.string().optional(),
partnerId: Joi.string().optional(),
token: Joi.string(),
recipientPublicKey: Joi.prefixedHexString(),
recipientVaultId: Joi.number().integer()
})
const feeRecipientSchema = Joi.object({
starkKey: Joi.prefixedHexString(),
vaultId: Joi.number().integer()
})
const errorProps = {context: 'transferUsingVaultIdAndStarkKey'}
const validateArg0 = validateWithJoi(transferDataSchema)('INVALID_METHOD_ARGUMENT')({
...errorProps, argIdx: 0
})
const validateArg1 = validateWithJoi(feeRecipientSchema)('INVALID_METHOD_ARGUMENT')({
...errorProps, argIdx: 1
})
module.exports = async (dvf, transferData, feesRecipient, createSignedTransferTx = makeCreateSignedTransferTx(dvf)) => {
const {
amount,
token,
recipientPublicKey,
recipientVaultId,
memo,
partnerId
} = validateArg0(transferData)
const tokenInfo = getValidTokenInfo(dvf)(token)
const quantisedAmount = getSafeQuantizedAmountOrThrow(amount, tokenInfo)
// tokenInfo.transferFee from conf as fee switch
if (!tokenInfo.transferFee || !feesRecipient) {
console.warn('No fees set for token or not recipient. Skipping fee tx', token, feesRecipient)
return createSignedTransferTx({
recipientPublicKey,
recipientVaultId,
tokenInfo,
quantisedAmount
})
}
// Fees are handled by deducting from the requested amount
// Two distinct txs are created : tx and feeTx with amount defined in conf
// On the server side, the two txs are processed atomically and
// fee amount and recipient are checked against current configuration
const {
starkKey: feeStarkKey,
vaultId: feeVaultId
} = validateArg1(feesRecipient)
const feeAmount = toQuantizedAmountBN(tokenInfo, tokenInfo.transferFee)
// Sign fees tx
const { tx: feeTx } = await createSignedTransferTx({
recipientPublicKey: feeStarkKey,
recipientVaultId: feeVaultId,
tokenInfo,
quantisedAmount: feeAmount
})
// Sign main tx
const { starkPublicKey, tx } = await createSignedTransferTx({
recipientPublicKey,
recipientVaultId,
tokenInfo,
quantisedAmount: quantisedAmount.minus(feeAmount)
})
return { tx, feeTx, starkPublicKey, memo, partnerId }
}