-
Notifications
You must be signed in to change notification settings - Fork 356
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new coin module boilerplate to help future integrations --------- Co-authored-by: Hedi EDELBLOUTE <[email protected]>
- Loading branch information
1 parent
03b94da
commit ddf8d85
Showing
56 changed files
with
1,809 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@ledgerhq/coin-module-boilerplate": patch | ||
--- | ||
|
||
feat: coin module boilerplate |
2 changes: 2 additions & 0 deletions
2
libs/coin-modules/coin-module-boilerplate/.env.integ.test.example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
PUB_KEY = "XPUB" | ||
SECRET_KEY = "SECRET" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
module.exports = { | ||
env: { | ||
browser: true, | ||
es6: true, | ||
}, | ||
overrides: [ | ||
{ | ||
files: ["src/**/*.test.{ts,tsx}"], | ||
env: { | ||
"jest/globals": true, | ||
}, | ||
plugins: ["jest"], | ||
}, | ||
], | ||
rules: { | ||
"no-console": ["error", { allow: ["warn", "error"] }], | ||
"@typescript-eslint/no-empty-function": "off", | ||
"no-empty-pattern": "off", | ||
"@typescript-eslint/no-explicit-any": "warn", | ||
"@typescript-eslint/no-unused-vars": "warn", | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.env.integ.test |
29 changes: 29 additions & 0 deletions
29
libs/coin-modules/coin-module-boilerplate/.unimportedrc.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"entry": [ | ||
"src/api/index.ts", | ||
"src/bridge/index.ts", | ||
"src/bridge/deviceTransactionConfig.ts", | ||
"src/datasets/dataset-1.ts", | ||
"src/signer/index.ts", | ||
"src/test/index.ts", | ||
"src/index.ts" | ||
], | ||
"ignorePatterns": [ | ||
"**/node_modules/**", | ||
"**/*.fixture.ts", | ||
"**/*.mock.ts", | ||
"**/*.test.{js,jsx,ts,tsx}" | ||
], | ||
"ignoreUnresolved": [ | ||
"jest-get-type", | ||
"jest-matcher-utils", | ||
"jest-message-util" | ||
], | ||
"ignoreUnimported": [ | ||
"src/network/mock-network.ts", | ||
"src/test/bot-specs.ts" | ||
], | ||
"ignoreUnused": [ | ||
"@ledgerhq/devices" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */ | ||
// `workerThreads: true` is required for validating object with `bigint` values | ||
module.exports = { | ||
preset: "ts-jest", | ||
testEnvironment: "node", | ||
testPathIgnorePatterns: ["lib/", "lib-es/", ".*\\.integ\\.test\\.[tj]s"], | ||
workerThreads: true, | ||
}; |
8 changes: 8 additions & 0 deletions
8
libs/coin-modules/coin-module-boilerplate/jest.integ.config.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */ | ||
module.exports = { | ||
preset: "ts-jest", | ||
testEnvironment: "node", | ||
testRegex: ".integ.test.ts$", | ||
testPathIgnorePatterns: ["lib/", "lib-es/"], | ||
setupFiles: ["dotenv/config"], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
{ | ||
"name": "@ledgerhq/coin-module-boilerplate", | ||
"version": "0.1.0", | ||
"description": "Boilerplate coin integration", | ||
"keywords": [ | ||
"Ledger", | ||
"LedgerWallet", | ||
"boilerplate", | ||
"Hardware Wallet" | ||
], | ||
"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-module-boilerplate", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"typesVersions": { | ||
"*": { | ||
"lib/*": [ | ||
"lib/*" | ||
], | ||
"lib-es/*": [ | ||
"lib-es/*" | ||
], | ||
"api": [ | ||
"lib/api/index" | ||
], | ||
"deviceTransactionConfig": [ | ||
"lib/bridge/deviceTransactionConfig" | ||
], | ||
"logic": [ | ||
"lib/logic/index" | ||
], | ||
"specs": [ | ||
"lib/test/bot-specs" | ||
], | ||
"transaction": [ | ||
"lib/bridge/transaction" | ||
], | ||
"types": [ | ||
"lib/types/index" | ||
], | ||
"*": [ | ||
"lib/*", | ||
"lib/bridge/*", | ||
"lib/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/logic/index.js", | ||
"default": "./lib-es/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/devices": "workspace:^", | ||
"@ledgerhq/errors": "workspace:^", | ||
"@ledgerhq/live-network": "workspace:^", | ||
"@ledgerhq/live-env": "workspace:^", | ||
"@ledgerhq/types-live": "workspace:^", | ||
"bignumber.js": "^9.1.2", | ||
"invariant": "^2.2.4", | ||
"rxjs": "^7.8.1" | ||
}, | ||
"devDependencies": { | ||
"@ledgerhq/types-cryptoassets": "workspace:^", | ||
"@types/invariant": "^2.2.37", | ||
"@types/jest": "^29.5.12", | ||
"dotenv": "^16.4.5", | ||
"expect": "^27.4.6", | ||
"jest": "^29.7.0", | ||
"ts-jest": "^29.1.1", | ||
"typescript": "^5.4.5" | ||
}, | ||
"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-boilerplate.json", | ||
"prewatch": "pnpm build", | ||
"watch": "tsc --watch", | ||
"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", | ||
"test-integ": "DOTENV_CONFIG_PATH=.env.integ.test jest --config=jest.integ.config.js", | ||
"typecheck": "tsc --noEmit", | ||
"unimported": "unimported" | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
libs/coin-modules/coin-module-boilerplate/src/api/index.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { createApi } from "."; | ||
import { BoilerplateConfig } from "../config"; | ||
|
||
describe("createApi", () => { | ||
it("should return every api methods", () => { | ||
const api = createApi({} as BoilerplateConfig); | ||
expect(api.broadcast).toBeDefined(); | ||
expect(api.combine).toBeDefined(); | ||
expect(api.craftTransaction).toBeDefined(); | ||
expect(api.estimateFees).toBeDefined(); | ||
expect(api.getBalance).toBeDefined(); | ||
expect(api.lastBlock).toBeDefined(); | ||
expect(api.listOperations).toBeDefined(); | ||
}); | ||
}); |
56 changes: 56 additions & 0 deletions
56
libs/coin-modules/coin-module-boilerplate/src/api/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import type { Api } from "@ledgerhq/coin-framework/api/index"; | ||
import coinConfig, { type BoilerplateConfig } from "../config"; | ||
import { | ||
broadcast, | ||
combine, | ||
craftTransaction, | ||
estimateFees, | ||
getBalance, | ||
getNextValidSequence, | ||
lastBlock, | ||
listOperations, | ||
} from "../common-logic"; | ||
import BigNumber from "bignumber.js"; | ||
|
||
export function createApi(config: BoilerplateConfig): Api { | ||
coinConfig.setCoinConfig(() => ({ ...config, status: { type: "active" } })); | ||
|
||
return { | ||
broadcast, | ||
combine, | ||
craftTransaction: craft, | ||
estimateFees: estimate, | ||
getBalance, | ||
lastBlock, | ||
listOperations, | ||
}; | ||
} | ||
|
||
async function craft( | ||
address: string, | ||
transaction: { | ||
recipient: string; | ||
amount: bigint; | ||
fee: bigint; | ||
}, | ||
): Promise<string> { | ||
const nextSequenceNumber = await getNextValidSequence(address); | ||
const tx = await craftTransaction( | ||
{ address, nextSequenceNumber }, | ||
{ | ||
recipient: transaction.recipient, | ||
amount: new BigNumber(transaction.amount.toString()), | ||
fee: new BigNumber(transaction.fee.toString()), | ||
}, | ||
); | ||
return tx.serializedTransaction; | ||
} | ||
|
||
// | ||
async function estimate(addr: string, amount: bigint): Promise<bigint> { | ||
const { serializedTransaction } = await craftTransaction( | ||
{ address: addr }, | ||
{ amount: new BigNumber(amount.toString()) }, | ||
); | ||
return BigInt((await estimateFees(serializedTransaction)).toString()); | ||
} |
36 changes: 36 additions & 0 deletions
36
libs/coin-modules/coin-module-boilerplate/src/bridge/broadcast.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { Account, BroadcastArg } from "@ledgerhq/types-live"; | ||
import { broadcast } from "./broadcast"; | ||
jest.mock("@ledgerhq/coin-framework/operation"); | ||
jest.mock("../common-logic"); | ||
import { patchOperationWithHash } from "@ledgerhq/coin-framework/operation"; | ||
import { broadcast as broadcastLogic } from "../common-logic"; | ||
|
||
describe("broadcast", () => { | ||
let patchOperationSpy: jest.SpyInstance; | ||
let broadcastSpy: jest.SpyInstance; | ||
beforeEach(() => { | ||
patchOperationSpy = jest.spyOn({ patchOperationWithHash }, "patchOperationWithHash"); | ||
broadcastSpy = jest.spyOn({ broadcastLogic }, "broadcastLogic"); | ||
broadcastSpy.mockResolvedValue("hash"); | ||
}); | ||
|
||
it("should broadcast", () => { | ||
broadcast({ | ||
signedOperation: { | ||
signature: undefined, | ||
operation: undefined, | ||
}, | ||
} as unknown as BroadcastArg<Account>); | ||
expect(broadcastLogic).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it("should patch operation with hash", () => { | ||
broadcast({ | ||
signedOperation: { | ||
signature: undefined, | ||
operation: undefined, | ||
}, | ||
} as unknown as BroadcastArg<Account>); | ||
expect(patchOperationSpy).toHaveBeenCalledWith(undefined, "hash"); | ||
}); | ||
}); |
11 changes: 11 additions & 0 deletions
11
libs/coin-modules/coin-module-boilerplate/src/bridge/broadcast.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { AccountBridge } from "@ledgerhq/types-live"; | ||
import { patchOperationWithHash } from "@ledgerhq/coin-framework/operation"; | ||
import { broadcast as broadcastLogic } from "../common-logic"; | ||
import { Transaction } from "../types"; | ||
|
||
export const broadcast: AccountBridge<Transaction>["broadcast"] = async ({ | ||
signedOperation: { signature, operation }, | ||
}) => { | ||
const hash = await broadcastLogic(signature); | ||
return patchOperationWithHash(operation, hash); | ||
}; |
12 changes: 12 additions & 0 deletions
12
libs/coin-modules/coin-module-boilerplate/src/bridge/createTransaction.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { Account, AccountLike } from "@ledgerhq/types-live"; | ||
import { createTransaction } from "./createTransaction"; | ||
|
||
describe("createTransaction", () => { | ||
it("should create a 0 amount transaction", () => { | ||
expect(createTransaction({} as AccountLike<Account>).amount.toNumber()).toEqual(0); | ||
}); | ||
|
||
it("should create a transaction with boilerplate family", () => { | ||
expect(createTransaction({} as AccountLike<Account>).family).toEqual("boilerplate"); | ||
}); | ||
}); |
14 changes: 14 additions & 0 deletions
14
libs/coin-modules/coin-module-boilerplate/src/bridge/createTransaction.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import BigNumber from "bignumber.js"; | ||
import { Transaction } from "../types"; | ||
import { AccountBridge } from "@ledgerhq/types-live"; | ||
|
||
// We create an empty transaction that will be filled later | ||
export const createTransaction: AccountBridge<Transaction>["createTransaction"] = () => ({ | ||
family: "boilerplate", | ||
amount: new BigNumber(0), | ||
recipient: "", | ||
fee: null, | ||
memo: undefined, | ||
networkInfo: null, | ||
feeCustomUnit: null, | ||
}); |
22 changes: 22 additions & 0 deletions
22
libs/coin-modules/coin-module-boilerplate/src/bridge/deviceTransactionConfig.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import getDeviceTransactionConfig from "./deviceTransactionConfig"; | ||
import BigNumber from "bignumber.js"; | ||
|
||
describe("getDeviceTransactionConfig", () => { | ||
it("should return amount field when it's more than 0", () => { | ||
expect( | ||
getDeviceTransactionConfig({ | ||
transaction: {}, | ||
status: { amount: new BigNumber(1), estimatedFees: new BigNumber(0) }, | ||
} as any)[0], | ||
).toEqual({ type: "amount", label: "Amount" }); | ||
}); | ||
|
||
it("should return fee field when it's more than 0", () => { | ||
expect( | ||
getDeviceTransactionConfig({ | ||
transaction: {}, | ||
status: { amount: new BigNumber(0), estimatedFees: new BigNumber(1) }, | ||
} as any)[0], | ||
).toEqual({ type: "fees", label: "Fees" }); | ||
}); | ||
}); |
Oops, something went wrong.