Skip to content

Commit

Permalink
Adding Address Class with tests and updating faucet_transaction test …
Browse files Browse the repository at this point in the history
…file name
  • Loading branch information
erdimaden committed May 14, 2024
1 parent 3efbe1e commit fc1202e
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 1 deletion.
87 changes: 87 additions & 0 deletions src/coinbase/address.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Address as AddressModel } from "../client";
import { InternalError } from "./errors";
import { FaucetTransaction } from "./faucet_transaction";
import { AddressClient } from "./types";

/**
* Class representing an Address in the Coinbase SDK.
*/
export class Address {
private model: AddressModel;
private client: AddressClient;

/**
* Creates an instance of Address.
* @param {AddressModel} model - The address model data.
* @param {AddressClient} client - The API client to interact with address-related endpoints.
* @throws {InternalError} If the model or client is empty.
*/
constructor(model: AddressModel, client: AddressClient) {
if (!model) {
throw new InternalError("Address model cannot be empty");
}
if (!client) {
throw new InternalError("Address client cannot be empty");
}
this.model = model;
this.client = client;
}

/**
* Requests faucet funds for the address.
* @returns {Promise<FaucetTransaction>} The faucet transaction object.
* @throws {InternalError} If the request does not return a transaction hash.
* @throws {Error} If the request fails.
*/
async faucet(): Promise<FaucetTransaction> {
try {
const response = await this.client.requestFaucetFunds(
this.model.wallet_id,
this.model.address_id,
);
return new FaucetTransaction(response.data);
} catch (e) {
throw new Error(`Failed to request faucet funds`);
}
}

/**
* Gets the address ID.
* @returns {string} The address ID.
*/
public getId(): string {
return this.model.address_id;
}

/**
* Gets the network ID.
* @returns {string} The network ID.
*/
public getNetworkId(): string {
return this.model.network_id;
}

/**
* Gets the public key.
* @returns {string} The public key.
*/
public getPublicKey(): string {
return this.model.public_key;
}

/**
* Gets the wallet ID.
* @returns {string} The wallet ID.
*/
public getWalletId(): string {
return this.model.wallet_id;
}

/**
* Returns a string representation of the address.
* @returns {string} A string representing the address.
*/
public toString(): string {
return `Coinbase:Address{addressId: '${this.model.address_id}', networkId: '${this.model.network_id}', walletId: '${this.model.wallet_id}'}`;
}
}
60 changes: 60 additions & 0 deletions src/coinbase/tests/address_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { AddressesApiFactory, Address as AddressModel } from "../../client";
import { Address } from "./../address";
import { FaucetTransaction } from "./../faucet_transaction";

import axios from "axios";
import MockAdapter from "axios-mock-adapter";

const axiosMock = new MockAdapter(axios);

const VALID_ADDRESS_MODEL: AddressModel = {
address_id: "mocked_address_id",
network_id: "mocked_network_id",
public_key: "mocked_public_key",
wallet_id: "mocked_wallet_id",
};

// Test suite for Address class
describe("Address", () => {
const client = AddressesApiFactory();

it("should create an Address instance", () => {
const address = new Address(VALID_ADDRESS_MODEL, client);
expect(address).toBeInstanceOf(Address);
expect(address.getId()).toBe("mocked_address_id");
expect(address.getNetworkId()).toBe("mocked_network_id");
expect(address.getPublicKey()).toBe("mocked_public_key");
expect(address.getWalletId()).toBe("mocked_wallet_id");
});

it("should throw an InternalError if model is not provided", () => {
expect(() => new Address(null!, client)).toThrow(`Address model cannot be empty`);
});

it("should throw an InternalError if client is not provided", () => {
expect(() => new Address(VALID_ADDRESS_MODEL, null!)).toThrow(`Address client cannot be empty`);
});

it("should request faucet funds and return a FaucetTransaction", async () => {
axiosMock.onPost().reply(200, {
transaction_hash: "mocked_transaction_hash",
});
const address = new Address(VALID_ADDRESS_MODEL, client);
const faucetTransaction = await address.faucet();
expect(faucetTransaction).toBeInstanceOf(FaucetTransaction);
expect(faucetTransaction.getTransactionHash()).toBe("mocked_transaction_hash");
});

it("should throw an error if faucet request fails", async () => {
axiosMock.onPost().reply(400);
const address = new Address(VALID_ADDRESS_MODEL, client);
await expect(address.faucet()).rejects.toThrow("Failed to request faucet funds");
});

it("should return the correct string representation", () => {
const address = new Address(VALID_ADDRESS_MODEL, client);
expect(address.toString()).toBe(
"Coinbase:Address{addressId: 'mocked_address_id', networkId: 'mocked_network_id', walletId: 'mocked_wallet_id'}",
);
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { InternalError } from "./../errors";
import { FaucetTransaction } from "../faucet_transaction";

describe("FaucetTransaction tests", () => {
Expand Down
17 changes: 17 additions & 0 deletions src/coinbase/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
import { AxiosPromise, AxiosRequestConfig } from "axios";
import { User as UserModel } from "./../client/api";

/**
* AddressAPI client type definition.
*/
export type AddressClient = {
/**
* Requests faucet funds for the address.
* @param {string} walletId - The wallet ID.
* @param {string} addressId - The address ID.
* @returns {Promise<{ data: { transaction_hash: string } }>} - The transaction hash
* @throws {Error} If the request fails.
*/
requestFaucetFunds(
walletId: string,
addressId: string,
): Promise<{ data: { transaction_hash: string } }>;
};

/**
* UserAPI client type definition.
*/
Expand Down

0 comments on commit fc1202e

Please sign in to comment.