-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1ef6712
commit ea478f1
Showing
5 changed files
with
478 additions
and
26 deletions.
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
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,176 @@ | ||
import { type PartialTezosOperation, TezosOperationType } from "@airgap/beacon-wallet"; | ||
import { mockContractAddress, mockImplicitAddress } from "@umami/tezos"; | ||
import { without } from "lodash"; | ||
|
||
import { makeAccountOperations } from "./AccountOperations"; | ||
import { partialOperationToOperation, toAccountOperations } from "./beaconUtils"; | ||
import { mockImplicitAccount, mockTezOperation } from "./testUtils"; | ||
|
||
const account = mockImplicitAccount(1); | ||
|
||
describe("toAccountOperations", () => { | ||
it("throws if the list is empty", () => { | ||
expect(() => toAccountOperations([], account)).toThrow("Empty operation details!"); | ||
}); | ||
|
||
it("converts a list of partial operations to ImplicitOperations", () => { | ||
const operationDetails: PartialTezosOperation[] = [ | ||
{ | ||
kind: TezosOperationType.TRANSACTION, | ||
amount: "1", | ||
destination: mockImplicitAddress(2).pkh, | ||
}, | ||
{ | ||
kind: TezosOperationType.TRANSACTION, | ||
amount: "2", | ||
destination: mockImplicitAddress(2).pkh, | ||
}, | ||
]; | ||
|
||
const operations = toAccountOperations(operationDetails, account); | ||
|
||
expect(operations).toEqual( | ||
makeAccountOperations(account, account, [ | ||
{ type: "tez", amount: "1", recipient: mockImplicitAddress(2) }, | ||
{ type: "tez", amount: "2", recipient: mockImplicitAddress(2) }, | ||
]) | ||
); | ||
}); | ||
}); | ||
|
||
describe("partialOperationToOperation", () => { | ||
describe.each( | ||
without( | ||
Object.values(TezosOperationType), | ||
TezosOperationType.TRANSACTION, | ||
TezosOperationType.DELEGATION, | ||
TezosOperationType.ORIGINATION | ||
) | ||
)("for %s", kind => { | ||
it("throws an error", () => { | ||
const operation: PartialTezosOperation = { kind } as PartialTezosOperation; | ||
|
||
expect(() => partialOperationToOperation(operation, account)).toThrow( | ||
`Unsupported operation kind: ${kind}` | ||
); | ||
}); | ||
}); | ||
|
||
test("tez transaction", () => { | ||
const operation: PartialTezosOperation = { | ||
kind: TezosOperationType.TRANSACTION, | ||
amount: "1", | ||
destination: mockImplicitAddress(2).pkh, | ||
}; | ||
|
||
const result = partialOperationToOperation(operation, account); | ||
|
||
expect(result).toEqual(mockTezOperation(1)); | ||
}); | ||
|
||
test("stake", () => { | ||
const operation: PartialTezosOperation = { | ||
kind: TezosOperationType.TRANSACTION, | ||
amount: "1", | ||
destination: mockImplicitAddress(2).pkh, | ||
parameters: { | ||
entrypoint: "stake", | ||
value: [{ prim: "UNIT" }], | ||
}, | ||
}; | ||
|
||
const result = partialOperationToOperation(operation, account); | ||
|
||
expect(result).toEqual({ | ||
type: "stake", | ||
amount: "1", | ||
sender: mockImplicitAddress(2), | ||
}); | ||
}); | ||
|
||
test("unstake", () => { | ||
const operation: PartialTezosOperation = { | ||
kind: TezosOperationType.TRANSACTION, | ||
amount: "12", | ||
destination: mockImplicitAddress(2).pkh, | ||
parameters: { | ||
entrypoint: "unstake", | ||
value: [{ prim: "UNIT" }], | ||
}, | ||
}; | ||
|
||
const result = partialOperationToOperation(operation, account); | ||
|
||
expect(result).toEqual({ | ||
type: "unstake", | ||
amount: "12", | ||
sender: mockImplicitAddress(2), | ||
}); | ||
}); | ||
|
||
test("finalize unstake", () => { | ||
const operation: PartialTezosOperation = { | ||
kind: TezosOperationType.TRANSACTION, | ||
destination: mockImplicitAddress(2).pkh, | ||
amount: "0", | ||
parameters: { | ||
entrypoint: "finalize_unstake", | ||
value: [{ prim: "UNIT" }], | ||
}, | ||
}; | ||
|
||
const result = partialOperationToOperation(operation, account); | ||
|
||
expect(result).toEqual({ | ||
type: "finalize_unstake", | ||
sender: mockImplicitAddress(2), | ||
}); | ||
}); | ||
|
||
test("contract call", () => { | ||
const operation: PartialTezosOperation = { | ||
kind: TezosOperationType.TRANSACTION, | ||
amount: "1", | ||
destination: mockContractAddress(2).pkh, | ||
parameters: { | ||
entrypoint: "mockEntrypoint", | ||
value: [{ prim: "UNIT" }], | ||
}, | ||
}; | ||
|
||
const result = partialOperationToOperation(operation, account); | ||
|
||
expect(result).toEqual({ | ||
type: "contract_call", | ||
amount: "1", | ||
contract: mockContractAddress(2), | ||
entrypoint: "mockEntrypoint", | ||
args: [{ prim: "UNIT" }], | ||
}); | ||
}); | ||
|
||
test("delegate", () => { | ||
const operation: PartialTezosOperation = { | ||
kind: TezosOperationType.DELEGATION, | ||
delegate: mockImplicitAddress(2).pkh, | ||
}; | ||
|
||
const result = partialOperationToOperation(operation, account); | ||
|
||
expect(result).toEqual({ | ||
type: "delegation", | ||
sender: account.address, | ||
recipient: mockImplicitAddress(2), | ||
}); | ||
}); | ||
|
||
test("undelegate", () => { | ||
const operation: PartialTezosOperation = { | ||
kind: TezosOperationType.DELEGATION, | ||
}; | ||
|
||
const result = partialOperationToOperation(operation, account); | ||
|
||
expect(result).toEqual({ type: "undelegation", sender: account.address }); | ||
}); | ||
}); |
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,109 @@ | ||
import { type PartialTezosOperation, TezosOperationType } from "@airgap/beacon-wallet"; | ||
import { isValidImplicitPkh, parseImplicitPkh, parsePkh } from "@umami/tezos"; | ||
|
||
import { type ImplicitAccount } from "./Account"; | ||
import { type ImplicitOperations } from "./AccountOperations"; | ||
import { type ContractOrigination, type Operation } from "./Operation"; | ||
|
||
/** | ||
* takes a list of {@link PartialTezosOperation} which come from Beacon | ||
* and converts them to {@link ImplicitOperations} | ||
* | ||
* @param operationDetails - the list of operations to convert | ||
* @param signer - the {@link Account} that's going to sign the operation | ||
* @returns | ||
*/ | ||
export const toAccountOperations = ( | ||
operationDetails: PartialTezosOperation[], | ||
signer: ImplicitAccount | ||
): ImplicitOperations => { | ||
if (operationDetails.length === 0) { | ||
throw new Error("Empty operation details!"); | ||
} | ||
|
||
const operations = operationDetails.map(operation => | ||
partialOperationToOperation(operation, signer) | ||
); | ||
|
||
return { | ||
type: "implicit", | ||
sender: signer, | ||
operations, | ||
signer, | ||
}; | ||
}; | ||
|
||
/** | ||
* Converts a {@link PartialTezosOperation} which comes from Beacon to a {@link Operation} | ||
* | ||
* Note: it doesn't supported all of the possible operation types, but only a subset of them. | ||
* | ||
* @param partialOperation - the operation to convert | ||
* @param signer - the {@link Account} that's going to sign the operation | ||
* @returns a parsed {@link Operation} | ||
*/ | ||
export const partialOperationToOperation = ( | ||
partialOperation: PartialTezosOperation, | ||
signer: ImplicitAccount | ||
): Operation => { | ||
switch (partialOperation.kind) { | ||
case TezosOperationType.TRANSACTION: { | ||
const { destination, amount, parameters } = partialOperation; | ||
if (parameters) { | ||
// if the destination is an implicit account then it's a pseudo operation | ||
if (isValidImplicitPkh(destination)) { | ||
switch (parameters.entrypoint) { | ||
case "stake": | ||
return { type: "stake", amount, sender: parseImplicitPkh(destination) }; | ||
case "unstake": | ||
return { type: "unstake", amount, sender: parseImplicitPkh(destination) }; | ||
case "finalize_unstake": | ||
return { type: "finalize_unstake", sender: parseImplicitPkh(destination) }; | ||
} | ||
} | ||
|
||
return { | ||
type: "contract_call", | ||
amount, | ||
contract: parsePkh(destination), | ||
entrypoint: parameters.entrypoint, | ||
args: parameters.value, | ||
}; | ||
} | ||
|
||
return { | ||
type: "tez", | ||
amount, | ||
recipient: parseImplicitPkh(partialOperation.destination), | ||
}; | ||
} | ||
case TezosOperationType.DELEGATION: { | ||
const { delegate } = partialOperation; | ||
|
||
if (delegate) { | ||
return { | ||
type: "delegation", | ||
sender: signer.address, | ||
recipient: parseImplicitPkh(delegate), | ||
}; | ||
} | ||
return { type: "undelegation", sender: signer.address }; | ||
} | ||
case TezosOperationType.ORIGINATION: { | ||
const { script } = partialOperation; | ||
const { code, storage } = script as unknown as { | ||
code: ContractOrigination["code"]; | ||
storage: ContractOrigination["storage"]; | ||
}; | ||
|
||
return { | ||
type: "contract_origination", | ||
sender: signer.address, | ||
code, | ||
storage, | ||
}; | ||
} | ||
default: | ||
throw new Error(`Unsupported operation kind: ${partialOperation.kind}`); | ||
} | ||
}; |
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
Oops, something went wrong.