cashramp
Version:
Cashramp API NodeJS SDK
430 lines (398 loc) • 14.7 kB
JavaScript
/**
* A response from the Cashramp API
* @typedef {Object} CashrampResponse
* @property {boolean} success True/false if the API request succeeds/fails
* @property {object} result The result of the API request
* @property {string} error The error message if the API request failed (ie. `success` = false)
*/
const fetch = require("node-fetch");
const {
AVAILABLE_COUNTRIES,
MARKET_RATE,
PAYMENT_METHOD_TYPES,
RAMPABLE_ASSETS,
RAMP_LIMITS,
PAYMENT_REQUEST,
RAMP_QUOTE,
ACCOUNT,
REFRESH_RAMP_QUOTE,
} = require("./queries");
const {
CONFIRM_TRANSACTION,
INITIATE_HOSTED_PAYMENT,
CANCEL_HOSTED_PAYMENT,
CREATE_CUSTOMER,
ADD_PAYMENT_METHOD,
WITHDRAW_ONCHAIN,
INITIATE_RAMP_QUOTE_DEPOSIT,
INITIATE_RAMP_QUOTE_WITHDRAWAL,
MARK_WITHDRAWAL_AS_RECEIVED,
MARK_DEPOSIT_AS_PAID,
CANCEL_DEPOSIT,
} = require("./mutations");
class Cashramp {
/**
* Cashramp API client
* @constructor
* @param {object} options Initialization options
* @param {"test"|"live"} options.env Preferred Cashramp environment
* @param {string} options.secretKey Your secret key
*/
constructor({ env, secretKey }) {
this._env = env || process.env.CASHRAMP_ENV || "live";
if (!["test", "live"].includes(this._env))
throw new Error(
`"${this._env}" is not a valid env. Can either be "test" or "live".`
);
this._secretKey = secretKey || process.env.CASHRAMP_SECRET_KEY;
if (!this._secretKey)
throw new Error("Please provide your API secret key.");
this._setup();
}
// QUERIES
/**
* Fetch the countries that Cashramp is available in
* @returns {CashrampResponse} response.result { id: string, name: string, code: string }
*/
async getAvailableCountries() {
return this.sendRequest({
name: "availableCountries",
query: AVAILABLE_COUNTRIES,
});
}
/**
* Fetch the Cashramp market rate for a country
* @param {object} options
* @param {string} options.countryCode The two-letter ISO 3166-1 country code
* @returns {CashrampResponse} response.result { depositRate: string, withdrawalRate: string }
*/
async getMarketRate({ countryCode }) {
return this.sendRequest({
name: "marketRate",
query: MARKET_RATE,
variables: { countryCode },
});
}
/**
* Fetch the payment method types available in a country
* @param {object} options
* @param {string} options.country The country's global ID
* @returns {CashrampResponse} response.result [{ id: string, identifier: string, fields: [{ label: string, identifier: string, required: boolean }]}]
*/
async getPaymentMethodTypes({ country }) {
return this.sendRequest({
name: "p2pPaymentMethodTypes",
query: PAYMENT_METHOD_TYPES,
variables: { country },
});
}
/**
* Fetch the assets you can on/offramp with the Onchain Ramp
* @returns {CashrampResponse} response.result [{ name: string, symbol: string, networks: [string], contractAddress: object }]
*/
async getRampableAssets() {
return this.sendRequest({ name: "rampableAssets", query: RAMPABLE_ASSETS });
}
/**
* Fetch the Onchain Ramp limits
* @returns {CashrampResponse} response.result { minimumDepositUsd: string, maximumDepositUsd: string, minimumWithdrawalUsd: string, maximumWithdrawalUsd: string, dailyLimitUsd: string }
*/
async getRampLimits() {
return this.sendRequest({ name: "rampLimits", query: RAMP_LIMITS });
}
/**
* Fetch the details of a payment request
* @param {object} options
* @param {string} reference The payment request's reference
* @returns {CashrampResponse}
*/
async getPaymentRequest({ reference }) {
return this.sendRequest({
name: "merchantPaymentRequest",
query: PAYMENT_REQUEST,
variables: { reference },
});
}
/**
* Request a new Ramp Quote for a Direct Ramp payment
* @param {object} options
* @param {string} options.customer The customer's global ID
* @param {number} options.amount The amount to ramp
* @param {"local_currency"|"usd"} options.currency The currency for the payment request
* @param {"deposit"|"withdrawal"} options.paymentType The type of payment request
* @param {string} options.paymentMethodType The payment method type's identifier
* @param {string} options.country Optional ISO 3166-2 country code (e.g 'GH', 'NG')
* @returns {CashrampResponse} response.result { id: string, exchangeRate: string, paymentType: string }
*/
async getRampQuote({ customer, amount, currency, paymentType, paymentMethodType, country }) {
return this.sendRequest({
name: "rampQuote",
query: RAMP_QUOTE,
variables: { customer, amount, currency, paymentType: paymentType || "deposit", paymentMethodType, country },
});
}
/**
* Refresh a Ramp Quote for a Direct Ramp payment
* @param {object} options
* @param {string} options.rampQuote The ramp quote's global ID
* @param {number} options.amount Optional new amount (keeps original if omitted)
* @returns {CashrampResponse} response.result { id: string, exchangeRate: string, paymentType: string }
*/
async refreshRampQuote({ rampQuote, amount }) {
return this.sendRequest({
name: "refreshRampQuote",
query: REFRESH_RAMP_QUOTE,
variables: { rampQuote, amount },
});
}
/**
* Fetch the account information for the authenticated user.
* @returns {CashrampResponse} response.result { accountBalance: string, depositAddress: string }
*/
async getAccount() {
return this.sendRequest({ name: "account", query: ACCOUNT });
}
// MUTATIONS
/**
* Confirm a crypto transfer sent into Cashramp's Secure Escrow address
* @param {object} options
* @param {string} options.paymentRequest The payment request's global ID
* @param {string} options.transactionHash The transaction hash of the crypto transfer sent to Cashramp's Secure Escrow address
* @returns {CashrampResponse}
*/
async confirmTransaction({ paymentRequest, transactionHash }) {
return this.sendRequest({
name: "confirmTransaction",
query: CONFIRM_TRANSACTION,
variables: { paymentRequest, transactionHash },
});
}
/**
* Initiate a payment request
* @param {object} options
* @param {number} options.amount The amount you want to deposit or withdraw
* @param {"local_currency"|"usd"} options.currency The currency for the payment request
* @param {string} options.countryCode The two-letter ISO 3166-1 country code
* @param {"deposit"|"withdrawal"} options.paymentType The type of payment request
* @param {string} options.reference An optional reference for the payment request
* @param {object} options.metadata An optional metadata object for the payment request echoed in webhooks
* @param {string} options.redirectUrl An optional URL to redirect to after the payment request is completed
* @param {string} options.firstName The customer's first name
* @param {string} options.lastName The customer's last name
* @param {string} options.email The customer's email address
* @returns {CashrampResponse} response.result { id: string, hostedLink: string, status: string }
*/
async initiateHostedPayment({
amount,
currency,
countryCode,
paymentType,
reference,
metadata,
redirectUrl,
firstName,
lastName,
email,
}) {
return this.sendRequest({
name: "initiateHostedPayment",
query: INITIATE_HOSTED_PAYMENT,
variables: {
amount,
currency: currency || "usd",
countryCode,
paymentType,
reference,
metadata,
redirectUrl,
firstName,
lastName,
email,
},
});
}
/**
* Cancel an ongoing payment request
* @param {object} options
* @param {string} options.paymentRequest The payment request's global ID
* @returns {CashrampResponse}
*/
async cancelHostedPayment({ paymentRequest }) {
return this.sendRequest({
name: "cancelHostedPayment",
query: CANCEL_HOSTED_PAYMENT,
variables: {
paymentRequest,
},
});
}
/**
* Initiate a Ramp Quote deposit
* @param {object} options
* @param {string} options.rampQuote The ramp quote's global ID
* @param {string} options.reference An optional reference for the payment request
* @param {string} options.phoneNumber Customer's phone number if paying via MoMo
* @param {string} options.bankAccountNumber Customer's bank account number if paying via bank
* @param {object} options.onchainTransferInfo Optional object for onchain stablecoin delivery
* @param {string} options.onchainTransferInfo.address Wallet address to receive stablecoins
* @param {string} options.onchainTransferInfo.cryptocurrency Cryptocurrency identifier (e.g., "usd_tether")
* @param {string} options.onchainTransferInfo.network Network to deliver on (e.g., "celo")
* @returns {CashrampResponse} response.result { id: string, status: string, agent: string, paymentDetails: string, exchangeRate: string, amountLocal: string, amountUsd: string, expiresAt: string }
*/
async initiateRampQuoteDeposit({ rampQuote, reference, phoneNumber, bankAccountNumber, onchainTransferInfo }) {
return this.sendRequest({
name: "initiateRampQuoteDeposit",
query: INITIATE_RAMP_QUOTE_DEPOSIT,
variables: { rampQuote, reference, phoneNumber, bankAccountNumber, onchainTransferInfo },
});
}
/**
* Initiate a Ramp Quote withdrawal
* @param {object} options
* @param {string} options.rampQuote The ramp quote's global ID
* @param {string} options.paymentMethod The payment method's global ID
* @param {string} options.reference An optional reference for the payment request
* @returns {CashrampResponse} response.result { id: string, status: string, agent: string, paymentDetails: string, exchangeRate: string, amountLocal: string, amountUsd: string }
*/
async initiateRampQuoteWithdrawal({ rampQuote, paymentMethod, reference }) {
return this.sendRequest({
name: "initiateRampQuoteWithdrawal",
query: INITIATE_RAMP_QUOTE_WITHDRAWAL,
variables: { rampQuote, paymentMethod, reference },
});
}
/**
* Mark a withdrawal payment request as received
* @param {object} options
* @param {string} options.paymentRequest The payment request's global ID
* @returns {CashrampResponse}
*/
async markWithdrawalAsReceived({ paymentRequest }) {
return this.sendRequest({
name: "markWithdrawalAsReceived",
query: MARK_WITHDRAWAL_AS_RECEIVED,
variables: { paymentRequest },
});
}
/**
* Mark a deposit payment request as paid
* @param {object} options
* @param {string} options.paymentRequest The payment request's global ID
* @param {string} options.receipt The receipt of the payment request
* @returns {CashrampResponse}
*/
async markDepositAsPaid({ paymentRequest, receipt }) {
return this.sendRequest({
name: "markDepositAsPaid",
query: MARK_DEPOSIT_AS_PAID,
variables: { paymentRequest, receipt },
});
}
/**
* Cancel a deposit payment request
* @param {object} options
* @param {string} options.paymentRequest The payment request's global ID
* @returns {CashrampResponse}
*/
async cancelDeposit({ paymentRequest }) {
return this.sendRequest({
name: "cancelDeposit",
query: CANCEL_DEPOSIT,
variables: { paymentRequest },
});
}
/**
* Create a new customer profile
* @param {object} options
* @param {string} options.firstName The customer's first name
* @param {string} options.lastName The customer's last name
* @param {string} options.email The customer's email address
* @returns {CashrampResponse}
*/
async createCustomer({ firstName, lastName, email, country }) {
return this.sendRequest({
name: "createCustomer",
query: CREATE_CUSTOMER,
variables: { firstName, lastName, email, country },
});
}
/**
* PaymentMethodField
* @typedef PaymentMethodField
* @property {string} identifier
* @property {string} value
*/
/**
* Add a payment method for an existing customer
* @param {object} options
* @param {string} options.customer The customer's global ID
* @param {string} options.paymentMethodType Identifier of the payment method type to add
* @param {[PaymentMethodField]} options.fields The fields of the payment method
* @returns {CashrampResponse}
*/
async addPaymentMethod({ customer, paymentMethodType, fields }) {
return this.sendRequest({
name: "addPaymentMethod",
query: ADD_PAYMENT_METHOD,
variables: { customer, paymentMethodType, fields },
});
}
/**
* Withdraw from your balance to an onchain wallet address
* @param {object} options
* @param {string} options.address The wallet address to withdraw to
* @param {number} options.amountUsd The amount to withdraw to the address provided
* @returns {CashrampResponse}
*/
async withdrawOnchain({ address, amountUsd }) {
return this.sendRequest({
name: "withdrawOnchain",
query: WITHDRAW_ONCHAIN,
variables: { address, amountUsd },
});
}
// GENERAL
/**
* Query the Cashramp API directly
* @param {object} options
* @param {string} options.name The name of the query/mutation
* @param {string} options.query The GraphQL query string
* @param {object} options.variables (Optional) Pass in variables for the GraphQL query
* @returns {CashrampResponse}
*/
async sendRequest({ name, query, variables }) {
try {
const response = await fetch(this._apiURL, {
method: "post",
body: JSON.stringify({
query,
variables,
}),
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${this._secretKey}`,
},
});
if (response.status == 200) {
const json = await response.json();
if (json.errors) {
return { success: false, error: json.errors[0].message };
} else {
return { success: true, result: json.data[name] };
}
} else {
return { success: false, error: response.statusText };
}
} catch (err) {
console.log(err);
return { success: false, error: err.message || "Something went wrong." };
}
}
// PRIVATE METHODS
_setup() {
let host = "api.useaccrue.com";
if (this._env == "test") host = `staging.${host}`;
this._apiURL = `https://${host}/cashramp/api/graphql`;
}
}
module.exports = Cashramp;