Skip to content

Commit

Permalink
feat: casper coin modularization
Browse files Browse the repository at this point in the history
  • Loading branch information
Canestin committed Jan 13, 2025
1 parent a15ee92 commit 9bcdecb
Show file tree
Hide file tree
Showing 66 changed files with 994 additions and 697 deletions.
6 changes: 6 additions & 0 deletions .changeset/chatty-days-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@ledgerhq/coin-casper": minor
"@ledgerhq/live-common": minor
---

casper coin modularization
46 changes: 46 additions & 0 deletions libs/coin-modules/coin-casper/.unimportedrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"entry": [
"src/api/api.ts",
"src/api/index.ts",
"src/bridge/bridgeHelpers/accountShape.ts",
"src/bridge/bridgeHelpers/addresses.ts",
"src/bridge/bridgeHelpers/fee.ts",
"src/bridge/bridgeHelpers/transferId.ts",
"src/bridge/bridgeHelpers/txn.ts",
"src/bridge/broadcast.ts",
"src/bridge/buildOptimisticOperation.ts",
"src/bridge/createTransaction.ts",
"src/bridge/deviceTransactionConfig.ts",
"src/bridge/estimateMaxSpendable.ts",
"src/bridge/getTransactionStatus.ts",
"src/bridge/index.ts",
"src/bridge/prepareTransaction.ts",
"src/bridge/signOperation.ts",
"src/bridge/transaction.ts",
"src/common-logic/index.ts",
"src/common-logic/utils.ts",
"src/consts.ts",
"src/errors.ts",
"src/hw-signMessage.ts",
"src/signer/getAddress.ts",
"src/signer/index.ts",
"src/test/bot-specs.ts",
"src/test/bridgeDatasetTest.ts",
"src/test/cli.ts",
"src/test/index.ts",
"src/test/speculos-deviceActions.ts",
"src/types/common.ts",
"src/types/index.ts",
"src/types/signer.ts",
"src/consts.ts",
"src/errors.ts",
"src/hw-signMessage.ts"
],
"ignoreUnresolved": [
"follow-redirects",
"form-data",
"proxy-from-env"
],
"ignoreUnused": [],
"ignoreUnimported": []
}
9 changes: 9 additions & 0 deletions libs/coin-modules/coin-casper/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */
module.exports = {
collectCoverageFrom: ["src/**/*.ts"],
coverageDirectory: "coverage",
preset: "ts-jest",
testEnvironment: "node",
testPathIgnorePatterns: ["lib/", "lib-es/"],
passWithNoTests: true,
};
126 changes: 126 additions & 0 deletions libs/coin-modules/coin-casper/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
{
"name": "@ledgerhq/coin-casper",
"version": "1.3.2",
"description": "Ledger Casper integration",
"keywords": [
"Ledger",
"LedgerWallet",
"Casper",
"CSPR"
],
"repository": {
"type": "git",
"url": "https://github.com/LedgerHQ/ledger-live.git"
},
"bugs": {
"url": "https://github.com/LedgerHQ/ledger-live/issues"
},
"homepage": "https://github.com/LedgerHQ/ledger-live/tree/develop/libs/coin-modules/coin-casper",
"publishConfig": {
"access": "public"
},
"typesVersions": {
"*": {
"lib/*": [
"lib/*"
],
"lib-es/*": [
"lib-es/*"
],
"specs": [
"lib/test/bot-specs"
],
"*": [
"lib/*",
"lib/api/*",
"lib/bridge/*",
"lib/common-logic/*",
"lib/signer/*",
"lib/test/*",
"lib/types/*"
]
}
},
"exports": {
"./lib/*": "./lib/*.js",
"./lib-es/*": "./lib-es/*.js",
"./api": {
"require": "./lib/api/index.js",
"default": "./lib-es/api/index.js"
},
"./deviceTransactionConfig": {
"require": "./lib/bridge/deviceTransactionConfig.js",
"default": "./lib-es/bridge/deviceTransactionConfig.js"
},
"./logic": {
"require": "./lib/common-logic/index.js",
"default": "./lib-es/common-logic/index.js"
},
"./signer": {
"require": "./lib/signer/index.js",
"default": "./lib-es/signer/index.js"
},
"./specs": {
"require": "./lib/test/bot-specs.js",
"default": "./lib-es/test/bot-specs.js"
},
"./transaction": {
"require": "./lib/bridge/transaction.js",
"default": "./lib-es/bridge/transaction.js"
},
"./types": {
"require": "./lib/types/index.js",
"default": "./lib-es/types/index.js"
},
"./*": {
"require": "./lib/*.js",
"default": "./lib-es/*.js"
},
".": {
"require": "./lib/index.js",
"default": "./lib-es/index.js"
},
"./package.json": "./package.json"
},
"license": "Apache-2.0",
"dependencies": {
"@ledgerhq/coin-framework": "workspace:^",
"@ledgerhq/cryptoassets": "workspace:^",
"@ledgerhq/types-cryptoassets": "workspace:^",
"@ledgerhq/devices": "workspace:*",
"@ledgerhq/errors": "workspace:^",
"@ledgerhq/live-env": "workspace:^",
"@ledgerhq/live-network": "workspace:^",
"@ledgerhq/logs": "workspace:^",
"@ledgerhq/types-live": "workspace:^",
"bignumber.js": "^9.1.2",
"invariant": "^2.2.2",
"lodash": "^4.17.21",
"casper-js-sdk": "^2.15.2",
"blakejs": "^1.2.1",
"rxjs": "^7.8.1",
"expect": "^27.4.6"
},
"devDependencies": {
"@types/invariant": "^2.2.2",
"@types/jest": "^29.5.10",
"@types/lodash": "^4.14.191",
"@types/semver": "^7.5.8",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"axios": "1.7.7"
},
"scripts": {
"clean": "rimraf lib lib-es",
"build": "tsc && tsc -m ES6 --outDir lib-es",
"coverage": "jest --coverage --testPathIgnorePatterns='/bridge.integration.test.ts|node_modules|lib-es|lib/' --passWithNoTests && mv coverage/coverage-final.json coverage/coverage-casper.json",
"prewatch": "pnpm build",
"watch": "tsc --watch",
"watch:es": "tsc --watch -m ES6 --outDir lib-es",
"doc": "documentation readme src/** --section=API --pe ts --re ts --re d.ts",
"lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx --cache",
"lint:fix": "pnpm lint --fix",
"test": "jest",
"unimported": "unimported"
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import flatMap from "lodash/flatMap";
import { log } from "@ledgerhq/logs";
import BigNumber from "bignumber.js";
import { encodeAccountId } from "../../../../account";

import { encodeAccountId } from "@ledgerhq/coin-framework/account/index";
import { GetAccountShape } from "@ledgerhq/coin-framework/bridge/jsHelpers";
import { fetchBalance, fetchNetworkStatus, fetchTxs, fetchAccountStateInfo } from "../../api/index";
import { mapTxToOps } from "./txn";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { log } from "@ledgerhq/logs";
import { Unit } from "@ledgerhq/types-cryptoassets";
import BigNumber from "bignumber.js";
import { DeployUtil } from "casper-js-sdk";
import { encodeOperationId } from "../../../../operation";
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
import { CASPER_NETWORK } from "../../consts";
import { casperAccountHashFromPublicKey, casperGetCLPublicKey, isAddressValid } from "./addresses";
import { ITxnHistoryData } from "../../api/types";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { DeployUtil } from "casper-js-sdk";
import { AccountBridge } from "@ledgerhq/types-live";
import { patchOperationWithHash } from "@ledgerhq/coin-framework/operation";
import { Transaction } from "./types";
import { broadcastTx } from "./api";
import { Transaction } from "../types";
import { broadcastTx } from "../api";

export const broadcast: AccountBridge<Transaction>["broadcast"] = async ({
signedOperation: { signature, operation },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { OperationType } from "@ledgerhq/types-live";
import { getAddress } from "./bridge/bridgeHelpers/addresses";
import { CasperAccount, CasperOperation, Transaction } from "./types";
import { encodeOperationId } from "../../operation";
import { getAddress } from "./bridgeHelpers/addresses";
import { CasperAccount, CasperOperation, Transaction } from "../types";
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";

export const buildOptimisticOperation = (
account: CasperAccount,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import BigNumber from "bignumber.js";
import { AccountBridge } from "@ledgerhq/types-live";
import { Transaction } from "./types";
import { Transaction } from "../types";

export const createTransaction: AccountBridge<Transaction>["createTransaction"] = () => {
// log("debug", "[createTransaction] creating base tx");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { log } from "@ledgerhq/logs";
import { Account, AccountLike } from "@ledgerhq/types-live";
import type { DeviceTransactionField } from "../../transaction";
import { Transaction, TransactionStatus } from "./types";
import { methodToString } from "./msc-utils";
import type { CommonDeviceTransactionField } from "@ledgerhq/coin-framework/transaction/common";
import { Transaction, TransactionStatus } from "../types";
import { methodToString } from "../common-logic";
import BigNumber from "bignumber.js";

export type ExtraDeviceTransactionField = {
Expand All @@ -11,6 +11,8 @@ export type ExtraDeviceTransactionField = {
value: number | BigNumber;
};

type DeviceTransactionField = CommonDeviceTransactionField | ExtraDeviceTransactionField;

function getDeviceTransactionConfig({
transaction,
}: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import BigNumber from "bignumber.js";
import { AccountBridge } from "@ledgerhq/types-live";
import { getMainAccount } from "@ledgerhq/coin-framework/account/index";
import { getEstimatedFees } from "./bridge/bridgeHelpers/fee";
import { Transaction } from "./types";
import { getEstimatedFees } from "./bridgeHelpers/fee";
import { Transaction } from "../types";

export const estimateMaxSpendable: AccountBridge<Transaction>["estimateMaxSpendable"] = async ({
account,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import {
NotEnoughBalance,
RecipientRequired,
} from "@ledgerhq/errors";
import { getAddress, isAddressValid } from "./bridge/bridgeHelpers/addresses";
import { CasperAccount, Transaction, TransactionStatus } from "./types";
import { isTransferIdValid } from "./bridge/bridgeHelpers/transferId";
import { CasperInvalidTransferId } from "./errors";
import { getAddress, isAddressValid } from "./bridgeHelpers/addresses";
import { CasperAccount, Transaction, TransactionStatus } from "../types";
import { isTransferIdValid } from "./bridgeHelpers/transferId";
import { CasperInvalidTransferId } from "../errors";
import {
CASPER_MINIMUM_VALID_AMOUNT_MOTES,
CASPER_MAX_TRANSFER_ID,
MayBlockAccountError,
InvalidMinimumAmountError,
} from "./consts";
} from "../consts";

export const getTransactionStatus: AccountBridge<
Transaction,
Expand Down
65 changes: 65 additions & 0 deletions libs/coin-modules/coin-casper/src/bridge/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
getSerializedAddressParameters,
makeAccountBridgeReceive,
makeScanAccounts,
makeSync,
updateTransaction,
} from "@ledgerhq/coin-framework/bridge/jsHelpers";
import resolver from "../signer";
import getAddressWrapper from "@ledgerhq/coin-framework/bridge/getAddressWrapper";
import { SignerContext } from "@ledgerhq/coin-framework/signer";
import type { Account, AccountBridge, CurrencyBridge } from "@ledgerhq/types-live";
import type { Transaction, TransactionStatus, CasperSigner } from "../types";
import { getTransactionStatus } from "./getTransactionStatus";
import { estimateMaxSpendable } from "./estimateMaxSpendable";
import { prepareTransaction } from "./prepareTransaction";
import { createTransaction } from "./createTransaction";
import { getAccountShape } from "./bridgeHelpers/accountShape";
import { buildSignOperation } from "./signOperation";
import { broadcast } from "./broadcast";

function buildCurrencyBridge(signerContext: SignerContext<CasperSigner>): CurrencyBridge {
const getAddress = resolver(signerContext);

const scanAccounts = makeScanAccounts({
getAccountShape,
getAddressFn: getAddressWrapper(getAddress),
});

return {
preload: () => Promise.resolve({}),
hydrate: () => {},
scanAccounts,
};
}

const sync = makeSync({ getAccountShape });

function buildAccountBridge(
signerContext: SignerContext<CasperSigner>,
): AccountBridge<Transaction, Account, TransactionStatus> {
const getAddress = resolver(signerContext);

const receive = makeAccountBridgeReceive(getAddressWrapper(getAddress));
const signOperation = buildSignOperation(signerContext);

return {
estimateMaxSpendable,
createTransaction,
updateTransaction,
getTransactionStatus,
prepareTransaction,
sync,
receive,
signOperation,
broadcast,
getSerializedAddressParameters,
};
}

export function createBridges(signerContext: SignerContext<CasperSigner>) {
return {
currencyBridge: buildCurrencyBridge(signerContext),
accountBridge: buildAccountBridge(signerContext),
};
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AccountBridge } from "@ledgerhq/types-live";
import { updateTransaction } from "@ledgerhq/coin-framework/bridge/jsHelpers";
import { getEstimatedFees } from "./bridge/bridgeHelpers/fee";
import { Transaction } from "./types";
import { getEstimatedFees } from "./bridgeHelpers/fee";
import { Transaction } from "../types";

export const prepareTransaction: AccountBridge<Transaction>["prepareTransaction"] = async (
account,
Expand Down
Loading

0 comments on commit 9bcdecb

Please sign in to comment.