UNPKG

cashramp

Version:
426 lines (394 loc) 14.2 kB
/** * 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 * @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 }) { return this.sendRequest({ name: "initiateRampQuoteDeposit", query: INITIATE_RAMP_QUOTE_DEPOSIT, variables: { rampQuote, reference, phoneNumber, bankAccountNumber }, }); } /** * 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;