Skip to content

Commit

Permalink
feat: add serialization of TokenAccount extra fields
Browse files Browse the repository at this point in the history
  • Loading branch information
mikhd committed Feb 15, 2024
1 parent 5423d9d commit 9fc214b
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 6 deletions.
26 changes: 26 additions & 0 deletions libs/ledger-live-common/src/account/serialization.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { getCryptoCurrencyById, getTokenById, setSupportedCurrencies } from "../currencies";
import { genAccount, genTokenAccount } from "@ledgerhq/coin-framework/mocks/account";
import { toAccountRaw, fromAccountRaw } from "./serialization";
import { setWalletAPIVersion } from "../wallet-api/version";
import { WALLET_API_VERSION } from "../wallet-api/constants";

setWalletAPIVersion(WALLET_API_VERSION);

setSupportedCurrencies(["solana"]);
const Solana = getCryptoCurrencyById("solana");
const USDC = getTokenById("solana/spl/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");

describe("serialization", () => {
test("TokenAccount extra fields should be serialized/deserialized", () => {
const acc: any = genAccount("mocked-account-1", { currency: Solana });
const tokenAcc: any = genTokenAccount(1, acc, USDC);
tokenAcc.state = "initialized";
acc.subAccounts = [tokenAcc];

const accRaw: any = toAccountRaw(acc);
expect(accRaw.subAccounts?.[0]?.state).toBe("initialized");

const deserializedAcc: any = fromAccountRaw(accRaw);
expect(deserializedAcc.subAccounts?.[0]?.state).toBe("initialized");
});
});
20 changes: 20 additions & 0 deletions libs/ledger-live-common/src/account/serialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,16 @@ export function fromAccountRaw(rawAccount: AccountRaw): Account {
if (assignFromAccountRaw) {
assignFromAccountRaw(rawAccount, res);
}

const assignFromTokenAccountRaw = bridge.assignFromTokenAccountRaw;
if (assignFromTokenAccountRaw) {
res.subAccounts?.forEach((subAcc, index) => {
const subAccRaw = subAccountsRaw?.[index];
if (subAcc.type === "TokenAccount" && subAccRaw?.type === "TokenAccountRaw") {
assignFromTokenAccountRaw(subAccRaw, subAcc);
}
});
}
}
}

Expand Down Expand Up @@ -496,6 +506,16 @@ export function toAccountRaw(account: Account): AccountRaw {
if (assignToAccountRaw) {
assignToAccountRaw(account, res);
}

const assignToTokenAccountRaw = bridge.assignToTokenAccountRaw;
if (assignToTokenAccountRaw) {
res.subAccounts?.forEach((subAccRaw, index) => {
const subAcc = subAccounts?.[index];
if (subAccRaw.type === "TokenAccountRaw" && subAcc?.type === "TokenAccount") {
assignToTokenAccountRaw(subAcc, subAccRaw);
}
});
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13052,5 +13052,7 @@ exports[`sortCurrenciesByIds snapshot 1`] = `
"cardano/native/f7c777fdd4531cf1c477551360e45b9684073c05c2fa61334f8f9add5665726974726565546f6b656e",
"stellar/asset/USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
"casper/asset/USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
"solana/spl/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"solana/spl/So11111111111111111111111111111111111111112",
]
`;
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ exports[`solana currency bridge scanAccounts solana seed 1 1`] = `
"pendingOperations": [],
"spendableBalance": "7960720",
"starred": false,
"state": "initialized",
"swapHistory": [],
"tokenId": "solana/spl/So11111111111111111111111111111111111111112",
"type": "TokenAccountRaw",
Expand Down
9 changes: 8 additions & 1 deletion libs/ledger-live-common/src/families/solana/bridge/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ import { PRELOAD_MAX_AGE, hydrate, preloadWithAPI } from "../js-preload";
import { prepareTransaction as prepareTransactionWithAPI } from "../js-prepareTransaction";
import { signOperationWithAPI } from "../js-signOperation";
import { getAccountShapeWithAPI } from "../js-synchronization";
import { assignFromAccountRaw, assignToAccountRaw } from "../serialization";
import {
assignFromAccountRaw,
assignFromTokenAccountRaw,
assignToAccountRaw,
assignToTokenAccountRaw,
} from "../serialization";
import type { SolanaAccount, SolanaPreloadDataV1, Transaction } from "../types";
import { endpointByCurrencyId } from "../utils";

Expand Down Expand Up @@ -164,6 +169,8 @@ export function makeBridges({
signOperation: makeSign(getAPI),
assignFromAccountRaw,
assignToAccountRaw,
assignFromTokenAccountRaw,
assignToTokenAccountRaw,
};

const currencyBridge: CurrencyBridge = {
Expand Down
31 changes: 29 additions & 2 deletions libs/ledger-live-common/src/families/solana/serialization.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { SolanaAccount, SolanaAccountRaw, SolanaResources, SolanaResourcesRaw } from "./types";
import { Account, AccountRaw } from "@ledgerhq/types-live";
import {
SolanaAccount,
SolanaAccountRaw,
SolanaResources,
SolanaResourcesRaw,
SolanaTokenAccount,
SolanaTokenAccountRaw,
} from "./types";
import { Account, AccountRaw, TokenAccount, TokenAccountRaw } from "@ledgerhq/types-live";
import { BigNumber } from "bignumber.js";

export function toSolanaResourcesRaw(resources: SolanaResources): SolanaResourcesRaw {
Expand Down Expand Up @@ -30,3 +37,23 @@ export function assignFromAccountRaw(accountRaw: AccountRaw, account: Account) {
if (solanaResourcesRaw)
(account as SolanaAccount).solanaResources = fromSolanaResourcesRaw(solanaResourcesRaw);
}

export function assignToTokenAccountRaw(
tokenAccount: TokenAccount,
tokenAccountRaw: TokenAccountRaw,
) {
const solanaTokenAccount = tokenAccount as SolanaTokenAccount;
if (solanaTokenAccount.state) {
(tokenAccountRaw as SolanaTokenAccountRaw).state = solanaTokenAccount.state;
}
}

export function assignFromTokenAccountRaw(
tokenAccountRaw: TokenAccountRaw,
tokenAccount: TokenAccount,
) {
const stateRaw = (tokenAccountRaw as SolanaTokenAccountRaw).state;
if (stateRaw) {
(tokenAccount as SolanaTokenAccount).state = stateRaw;
}
}
32 changes: 30 additions & 2 deletions libs/ledgerjs/packages/types-live/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,12 @@ Ledger Live main types.
* [Parameters](#parameters)
* [assignFromAccountRaw](#assignfromaccountraw)
* [Parameters](#parameters-1)
* [initAccount](#initaccount)
* [assignToTokenAccountRaw](#assigntotokenaccountraw)
* [Parameters](#parameters-2)
* [assignFromTokenAccountRaw](#assignfromtokenaccountraw)
* [Parameters](#parameters-3)
* [initAccount](#initaccount)
* [Parameters](#parameters-4)
* [CurrenciesData](#currenciesdata)
* [Properties](#properties-11)
* [DatasetTest](#datasettest)
Expand Down Expand Up @@ -483,6 +487,30 @@ Type: function (accountRaw: [AccountRaw](#accountraw), account: [Account](#accou
* `accountRaw` **[AccountRaw](#accountraw)** The account in its serialized form.
* `account` **[Account](#account)** The original account object.

#### assignToTokenAccountRaw

This function mutates the 'tokenAccountRaw' object in-place to add any extra fields that the coin may need to set.
It is called during the serialization mechanism

Type: function (tokenAccount: [TokenAccount](#tokenaccount), tokenAccountRaw: [TokenAccountRaw](#tokenaccountraw)): void

##### Parameters

* `tokenAccount` **[TokenAccount](#tokenaccount)** The original token account object.
* `tokenAccountRaw` **[TokenAccountRaw](#tokenaccountraw)** The token account in its serialized form.

#### assignFromTokenAccountRaw

This function mutates the 'tokenAccount' object in-place to add any extra fields that the coin may need to set.
It is called during the deserialization mechanism

Type: function (tokenAccountRaw: [TokenAccountRaw](#tokenaccountraw), tokenAccount: [TokenAccount](#tokenaccount)): void

##### Parameters

* `tokenAccountRaw` **[TokenAccountRaw](#tokenaccountraw)** The token account in its serialized form.
* `tokenAccount` **[TokenAccount](#tokenaccount)** The original token account object.

#### initAccount

This function mutates the 'account' object to extend it with any extra fields of the coin.
Expand Down Expand Up @@ -1009,7 +1037,7 @@ Type: {ticker: [string](https://developer.mozilla.org/docs/Web/JavaScript/Refere

### OperationType

Type: (`"IN"` | `"OUT"` | `"NONE"` | `"CREATE"` | `"REVEAL"` | `"DELEGATE"` | `"UNDELEGATE"` | `"REDELEGATE"` | `"REWARD"` | `"FEES"` | `"FREEZE"` | `"UNFREEZE"` | `"WITHDRAW_EXPIRE_UNFREEZE"` | `"UNDELEGATE_RESOURCE"` | `"LEGACY_UNFREEZE"` | `"VOTE"` | `"REWARD_PAYOUT"` | `"BOND"` | `"UNBOND"` | `"WITHDRAW_UNBONDED"` | `"SET_CONTROLLER"` | `"SLASH"` | `"NOMINATE"` | `"CHILL"` | `"APPROVE"` | `"OPT_IN"` | `"OPT_OUT"` | `"LOCK"` | `"UNLOCK"` | `"WITHDRAW"` | `"REVOKE"` | `"ACTIVATE"` | `"REGISTER"` | `"NFT_IN"` | `"NFT_OUT"` | `"STAKE"` | `"UNSTAKE"` | `"WITHDRAW_UNSTAKED"`)
Type: (`"IN"` | `"OUT"` | `"NONE"` | `"CREATE"` | `"REVEAL"` | `"DELEGATE"` | `"UNDELEGATE"` | `"REDELEGATE"` | `"REWARD"` | `"FEES"` | `"FREEZE"` | `"UNFREEZE"` | `"WITHDRAW_EXPIRE_UNFREEZE"` | `"UNDELEGATE_RESOURCE"` | `"LEGACY_UNFREEZE"` | `"VOTE"` | `"REWARD_PAYOUT"` | `"BOND"` | `"UNBOND"` | `"WITHDRAW_UNBONDED"` | `"SET_CONTROLLER"` | `"SLASH"` | `"NOMINATE"` | `"CHILL"` | `"APPROVE"` | `"OPT_IN"` | `"OPT_OUT"` | `"LOCK"` | `"UNLOCK"` | `"WITHDRAW"` | `"REVOKE"` | `"ACTIVATE"` | `"REGISTER"` | `"NFT_IN"` | `"NFT_OUT"` | `"STAKE"` | `"UNSTAKE"` | `"WITHDRAW_UNSTAKED"` | `"BURN"`)

### Operation

Expand Down
21 changes: 20 additions & 1 deletion libs/ledgerjs/packages/types-live/src/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { BigNumber } from "bignumber.js";
import type { Observable } from "rxjs";
import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
import type { AccountLike, Account, AccountRaw } from "./account";
import type { AccountLike, Account, AccountRaw, TokenAccount, TokenAccountRaw } from "./account";
import type {
SignOperationEvent,
SignedOperation,
Expand Down Expand Up @@ -182,6 +182,25 @@ export interface AccountBridge<T extends TransactionCommon> {
* @param {Account} account - The original account object.
*/
assignFromAccountRaw?: (accountRaw: AccountRaw, account: Account) => void;
/**
* This function mutates the 'tokenAccountRaw' object in-place to add any extra fields that the coin may need to set.
* It is called during the serialization mechanism
*
* @param {TokenAccount} tokenAccount - The original token account object.
* @param {TokenAccountRaw} tokenAccountRaw - The token account in its serialized form.
*/
assignToTokenAccountRaw?: (tokenAccount: TokenAccount, tokenAccountRaw: TokenAccountRaw) => void;
/**
* This function mutates the 'tokenAccount' object in-place to add any extra fields that the coin may need to set.
* It is called during the deserialization mechanism
*
* @param {TokenAccountRaw} tokenAccountRaw - The token account in its serialized form.
* @param {TokenAccount} tokenAccount - The original token account object.
*/
assignFromTokenAccountRaw?: (
tokenAccountRaw: TokenAccountRaw,
tokenAccount: TokenAccount,
) => void;
/**
* This function mutates the 'account' object to extend it with any extra fields of the coin.
* For instance bitcoinResources needs to be created.
Expand Down

0 comments on commit 9fc214b

Please sign in to comment.