@ledgerhq/coin-casper
Version:
Ledger Casper integration
306 lines • 13.5 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const txn_1 = require("./txn");
const addresses_1 = require("./addresses");
const fixtures = __importStar(require("../../test/fixtures"));
const txn_2 = require("./txn");
// Import Casper SDK mock for direct access to mocks
// eslint-disable-next-line @typescript-eslint/no-var-requires
const mockCasperSDK = require("casper-js-sdk");
// Mock the entire Casper SDK
jest.mock("casper-js-sdk", () => {
const mockTransaction = { id: "mock-transaction" };
const mockHelper = {
createTransferTransaction: jest.fn().mockReturnValue(mockTransaction),
};
return {
CasperNetwork: {
create: jest.fn().mockResolvedValue(mockHelper),
},
PublicKey: {
fromHex: jest.fn().mockReturnValue({ value: "mocked-public-key" }),
},
Transaction: jest.fn().mockImplementation(() => mockTransaction),
};
});
jest.mock("@ledgerhq/coin-framework/operation", () => ({
encodeOperationId: jest.fn((accountId, hash, type) => `${accountId}-${hash}-${type}`),
}));
jest.mock("./addresses", () => ({
casperAccountHashFromPublicKey: jest.fn((key) => `account-hash-${key}`),
isAddressValid: jest.fn(),
}));
jest.mock("../../api", () => ({
getCasperNodeRpcClient: jest.fn(),
}));
describe("txn", () => {
// Reset mocks between tests
beforeEach(() => {
jest.clearAllMocks();
});
describe("getUnit", () => {
test("should return the first unit of casper currency", () => {
const unit = (0, txn_1.getUnit)();
expect(unit).toBeDefined();
expect(unit.name).toBe("CSPR");
expect(unit.code).toBe("CSPR");
expect(unit.magnitude).toBe(9);
});
});
describe("mapTxToOps", () => {
const { mockAccountId } = fixtures.createMockAccountShapeData();
const fees = new bignumber_js_1.default("100000000");
const mockTimestamp = "2023-01-01T12:00:00Z";
beforeEach(() => {
addresses_1.casperAccountHashFromPublicKey.mockImplementation((key) => `account-hash-${key}`);
});
test("should map an outgoing transaction to operation", () => {
// Use a modified version of the fixture tx data
const fixtureData = fixtures.createMockAccountShapeData();
const txData = {
...fixtureData.mockTxs[0],
timestamp: mockTimestamp,
caller_public_key: "owner-public-key",
args: {
target: {
cl_type: "PublicKey",
parsed: "recipient-public-key",
},
amount: {
parsed: "5000000000",
cl_type: "U512",
},
id: {
parsed: 12345,
cl_type: {
Option: "U64",
},
},
},
deploy_hash: "test-deploy-hash",
status: "success",
amount: "5000000000",
};
// Set up the owner address hash to match the from account hash
addresses_1.casperAccountHashFromPublicKey.mockReturnValueOnce("account-hash-owner-public-key");
addresses_1.casperAccountHashFromPublicKey.mockReturnValueOnce("account-hash-recipient-public-key");
const mapper = (0, txn_1.mapTxToOps)(mockAccountId, "account-hash-owner-public-key", fees);
const operations = mapper(txData);
expect(operations).toHaveLength(1);
expect(operations[0]).toEqual({
id: `${mockAccountId}-${txData.deploy_hash}-OUT`,
hash: txData.deploy_hash,
type: "OUT",
value: new bignumber_js_1.default("5000000000").plus(fees),
fee: fees,
blockHeight: 1,
hasFailed: false,
blockHash: null,
accountId: mockAccountId,
senders: ["account-hash-owner-public-key"],
recipients: ["account-hash-recipient-public-key"],
date: new Date(mockTimestamp),
extra: {
transferId: "12345",
},
});
});
test("should map an incoming transaction to operation", () => {
const recipientAddressHash = "account-hash-owner-public-key";
// Use a modified version of the fixture tx data
const fixtureData = fixtures.createMockAccountShapeData();
const txData = {
...fixtureData.mockTxs[0],
timestamp: mockTimestamp,
caller_public_key: "sender-public-key",
args: {
target: {
cl_type: "PublicKey",
parsed: "owner-public-key",
},
amount: {
parsed: "5000000000",
cl_type: "U512",
},
id: {
parsed: 12345,
cl_type: {
Option: "U64",
},
},
},
deploy_hash: "test-deploy-hash",
status: "success",
amount: "5000000000",
};
addresses_1.casperAccountHashFromPublicKey.mockReturnValueOnce("account-hash-sender-public-key");
addresses_1.casperAccountHashFromPublicKey.mockReturnValueOnce(recipientAddressHash);
const mapper = (0, txn_1.mapTxToOps)(mockAccountId, recipientAddressHash, fees);
const operations = mapper(txData);
expect(operations).toHaveLength(1);
expect(operations[0]).toEqual({
id: `${mockAccountId}-${txData.deploy_hash}-IN`,
hash: txData.deploy_hash,
type: "IN",
value: new bignumber_js_1.default("5000000000"),
fee: fees,
blockHeight: 1,
hasFailed: false,
blockHash: null,
accountId: mockAccountId,
senders: ["account-hash-sender-public-key"],
recipients: [recipientAddressHash],
date: new Date(mockTimestamp),
extra: {
transferId: "12345",
},
});
});
test("should map a failed transaction correctly", () => {
// Use a modified version of the fixture tx data
const fixtureData = fixtures.createMockAccountShapeData();
const txData = {
...fixtureData.mockTxs[0],
timestamp: mockTimestamp,
caller_public_key: "owner-public-key",
args: {
target: {
cl_type: "PublicKey",
parsed: "recipient-public-key",
},
amount: {
parsed: "5000000000",
cl_type: "U512",
},
id: {
parsed: 12345,
cl_type: {
Option: "U64",
},
},
},
deploy_hash: "test-deploy-hash",
error_message: "Transaction failed due to insufficient funds",
status: "failure",
amount: "5000000000",
};
addresses_1.casperAccountHashFromPublicKey.mockReturnValueOnce("account-hash-owner-public-key");
addresses_1.casperAccountHashFromPublicKey.mockReturnValueOnce("account-hash-recipient-public-key");
const mapper = (0, txn_1.mapTxToOps)(mockAccountId, "account-hash-owner-public-key", fees);
const operations = mapper(txData);
expect(operations).toHaveLength(1);
expect(operations[0].hasFailed).toBe(true);
});
test("should handle target as account hash string directly", () => {
// Use a modified version of the fixture tx data
const fixtureData = fixtures.createMockAccountShapeData();
const txData = {
...fixtureData.mockTxs[0],
timestamp: mockTimestamp,
caller_public_key: "owner-public-key",
args: {
target: {
cl_type: {
ByteArray: 32,
},
parsed: "account-hash-direct-address",
},
amount: {
parsed: "5000000000",
cl_type: "U512",
},
id: {
parsed: 12345,
cl_type: {
Option: "U64",
},
},
},
deploy_hash: "test-deploy-hash",
status: "success",
amount: "5000000000",
};
addresses_1.casperAccountHashFromPublicKey.mockReturnValueOnce("account-hash-owner-public-key");
const mapper = (0, txn_1.mapTxToOps)(mockAccountId, "account-hash-owner-public-key", fees);
const operations = mapper(txData);
expect(operations).toHaveLength(1);
expect(operations[0].recipients).toEqual(["account-hash-direct-address"]);
});
test("should catch and log errors when mapping fails", () => {
const txData = {
timestamp: mockTimestamp,
caller_public_key: "owner-public-key",
args: {
// Intentionally missing the target field to cause an error
amount: {
parsed: "5000000000",
cl_type: "U512",
},
},
deploy_hash: "test-deploy-hash",
block_hash: "block-hash-1",
execution_type_id: 1,
cost: "100000",
payment_amount: "100000000",
status: "success",
amount: "5000000000",
};
const mapper = (0, txn_1.mapTxToOps)(mockAccountId, "account-hash-owner-public-key", fees);
const operations = mapper(txData);
expect(operations).toEqual([]);
});
});
describe("createNewTransaction", () => {
const { mockAddress: mockSender } = fixtures.createMockAccountShapeData();
const mockRecipient = fixtures.TEST_ADDRESSES.RECIPIENT_SECP256K1;
const mockAmount = new bignumber_js_1.default("5000000000");
const mockFees = new bignumber_js_1.default("100000000");
const mockTransferId = fixtures.TEST_TRANSFER_IDS.VALID;
// Direct access to the mocks from jest.mock
const mockCreateNetwork = mockCasperSDK.CasperNetwork.create;
const mockPublicKeyFromHex = mockCasperSDK.PublicKey.fromHex;
beforeEach(() => {
addresses_1.isAddressValid.mockReturnValue(true);
});
test("should throw error if recipient address is invalid", async () => {
addresses_1.isAddressValid.mockReturnValue(false);
await expect((0, txn_2.createNewTransaction)(mockSender, mockRecipient, mockAmount, mockFees)).rejects.toThrow();
});
test("should create a new transaction with valid parameters", async () => {
const expectedTransaction = { id: "mock-transaction" };
const result = await (0, txn_2.createNewTransaction)(mockSender, mockRecipient, mockAmount, mockFees, mockTransferId);
expect(result).toEqual(expectedTransaction);
expect(mockCreateNetwork).toHaveBeenCalled();
expect(mockPublicKeyFromHex).toHaveBeenCalledWith(mockSender);
expect(mockPublicKeyFromHex).toHaveBeenCalledWith(mockRecipient);
});
});
});
//# sourceMappingURL=txn.test.js.map