multiversx / mx-sdk-js-network-providers

Network Provider (API, Gateway) components (compatible with sdk-js).
Other
6 stars 6 forks source link

WIP - Breaking change: decouple from "axios" #53

Open andreibancioiu opened 9 months ago

andreibancioiu commented 9 months ago

While axios is a great library, we'd like to decouple sdk-network-providers from it - so that issues related to axios do not impact this package anymore.

Breaking change: the constructors ApiNetworkProvider and ProxyNetworkProvider have been altered (see snippet below).

Client code would now be responsible with providing a httpProvider when instantiating ApiNetworkProvider or ProxyNetworkProvider.

A httpProvider must satisfy the following interface:

export interface IHttpProvider {
    get(url: string): Promise<any>;
    post(url: string, payload: any): Promise<any>;
    // TBD: error handling
}

Such a httpProvider can be power, indeed, by axios. For example:

const apiProvider: INetworkProvider = new ApiNetworkProvider({
    baseUrl: "https://devnet-api.multiversx.com",
    httpProvider: createHttpProvider()
});

const proxyProvider: INetworkProvider = new ProxyNetworkProvider({
    baseUrl: "https://devnet-gateway.multiversx.com",
    httpProvider: createHttpProvider()
});

// Depends on:
// - https://www.npmjs.com/package/axios
// - https://www.npmjs.com/package/json-bigint
function createHttpProvider() {
    const axios = require("axios").default;
    const jsonBig = require("json-bigint")({ constructorAction: "ignore" });

    const axiosConfig = {
        timeout: 10000,
        // See: https://github.com/axios/axios/issues/983 regarding transformResponse
        // Very important, to properly handle responses bearing big integers.
        transformResponse: [
            function (data: any) {
                return jsonBig.parse(data);
            }
        ],
        headers: {
            "Content-Type": "application/json"
        }
    };

    return {
        async get(url: string) {
            return (await axios.get(url, axiosConfig)).data;
        },
        async post(url: string, payload: any) {
            return (await axios.post(url, payload, axiosConfig)).data;
        }
    };
}

This design change also allows the code that depends on ApiNetworkProvider or ProxyNetworkProvider to be tested in a less complex fashion - since passing a mock IHttpProvider would be much simpler than using special axios mock adapters.