Skip to content

Commit

Permalink
added transfer ticket to the wallet API and updated integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dsawali committed Jul 3, 2024
1 parent 97832fc commit dc9fafc
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { CONFIGS } from '../../config';
import { DefaultContractType, TezosToolkit } from '@taquito/taquito';
import { ticketsSendTz } from '../../data/code_with_ticket_transfer';
import { RpcClient, TicketTokenParams } from '@taquito/rpc';

CONFIGS().forEach(({ lib, rpc, setup, createAddress }) => {
const Tezos = lib;
const client = new RpcClient(rpc);

let ticketSendContract: DefaultContractType;
let recipient: TezosToolkit;
let sender: TezosToolkit;
let recipientPkh: string;
let senderPkh: string
let ticketToken: TicketTokenParams;

describe(`Transfer tickets between implicit accounts using: ${rpc}`, () => {

beforeAll(async () => {
await setup(true);
try {
recipient = await createAddress();
sender = await createAddress();

recipientPkh = await recipient.signer.publicKeyHash();
senderPkh = await sender.wallet.pkh();

const fundSender = await Tezos.contract.transfer({ to: senderPkh, amount: 5 });
await fundSender.confirmation();

const ticketSendOrigination = await Tezos.contract.originate({ code: ticketsSendTz, storage: null });
await ticketSendOrigination.confirmation();

ticketSendContract = await ticketSendOrigination.contract();
ticketToken = { ticketer: ticketSendContract.address, content_type: { prim: 'string' }, content: { string: 'Ticket' } };

// Send 3 tickets from the originated contract to sender
const sendTickets = await ticketSendContract.methods.default(senderPkh, '3').send();
await sendTickets.confirmation();
} catch (error) {
console.log(error);
}
});

it('should transfer 1 ticket from an implicit account to another implicit account using a Wallet', async () => {
// Check balances before transferring tickets
const balanceBefore = await client.getTicketBalance(recipientPkh, ticketToken);
expect(balanceBefore).toEqual('0');

const senderBalanceBefore = await client.getTicketBalance(senderPkh, ticketToken);
expect(senderBalanceBefore).toEqual('3');

// Transfer 1 ticket from sender to recipient
const transferTicketOp = await sender.wallet.transferTicket({
ticketContents: { string: "Ticket" },
ticketTy: { prim: "string" },
ticketTicketer: ticketSendContract.address,
ticketAmount: 1,
destination: recipientPkh,
entrypoint: 'default',
}).send();

await transferTicketOp.confirmation();

expect(await transferTicketOp.status()).toEqual('applied');
console.log(`opHash: ${transferTicketOp.opHash}`);

// Check balances after transferring tickets
const balanceAfter = await client.getTicketBalance(recipientPkh, ticketToken);
expect(balanceAfter).toEqual('1');

const senderBalanceAfter = await client.getTicketBalance(senderPkh, ticketToken);
expect(senderBalanceAfter).toEqual('2');
});
});
});
17 changes: 17 additions & 0 deletions packages/taquito-beacon-wallet/src/taquito-beacon-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {
WalletStakeParams,
WalletUnstakeParams,
WalletFinalizeUnstakeParams,
WalletTransferTicketParams,
createTransferTicketOperation,
} from '@taquito/taquito';
import { buf2hex, hex2buf, mergebuf } from '@taquito/utils';
import { UnsupportedActionError } from '@taquito/core';
Expand Down Expand Up @@ -97,6 +99,21 @@ export class BeaconWallet implements WalletProvider {
);
}

async mapTransferTicketParamsToWalletParams(params: () => Promise<WalletTransferTicketParams>) {
let walletParams: WalletTransferTicketParams;
await this.client.showPrepare();
try {
walletParams = await params();
} catch (err) {
await this.client.hideUI(['alert']);
throw err;
}
return this.removeDefaultParams(
walletParams,
await createTransferTicketOperation(this.formatParameters(walletParams))
);
}

async mapStakeParamsToWalletParams(params: () => Promise<WalletStakeParams>) {
let walletParams: WalletStakeParams;
await this.client.showPrepare();
Expand Down
1 change: 1 addition & 0 deletions packages/taquito/src/wallet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export * from './operation';
export * from './transaction-operation';
export * from './origination-operation';
export * from './delegation-operation';
export * from './transfer-ticket-operation';
export * from './interface';
export * from './legacy';
10 changes: 10 additions & 0 deletions packages/taquito/src/wallet/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
StakeParams,
UnstakeParams,
FinalizeUnstakeParams,
TransferTicketParams,
} from '../operations/types';

export type WalletDefinedFields = 'source';
Expand All @@ -30,6 +31,8 @@ export type WalletFailingNoopParams = Omit<FailingNoopParams, WalletDefinedField

export type WalletIncreasePaidStorageParams = Omit<IncreasePaidStorageParams, WalletDefinedFields>;

export type WalletTransferTicketParams = Omit<TransferTicketParams, WalletDefinedFields>;

export interface WalletProvider {
/**
* @description Request the public key hash from the wallet
Expand All @@ -46,6 +49,13 @@ export interface WalletProvider {
*/
mapTransferParamsToWalletParams: (params: () => Promise<WalletTransferParams>) => Promise<any>;

/**
* @description Transform WalletTransferTicketParams into a format compliant with the underlying wallet
*/
mapTransferTicketParamsToWalletParams: (
params: () => Promise<WalletTransferTicketParams>
) => Promise<any>;

/**
* @description Transform WalletStakeParams into a format compliant with the underlying wallet
*/
Expand Down
5 changes: 5 additions & 0 deletions packages/taquito/src/wallet/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
WalletStakeParams,
WalletUnstakeParams,
WalletFinalizeUnstakeParams,
WalletTransferTicketParams,
} from './interface';
import { WalletParamsWithKind } from './wallet';

Expand Down Expand Up @@ -51,6 +52,10 @@ export class LegacyWalletProvider implements WalletProvider {
return attachKind(await params(), OpKind.INCREASE_PAID_STORAGE);
}

async mapTransferTicketParamsToWalletParams(params: () => Promise<WalletTransferTicketParams>) {
return attachKind(await params(), OpKind.TRANSFER_TICKET);
}

async sendOperations(params: WalletParamsWithKind[]) {
const op = await this.context.batch.batch(params as any).send();
return op.hash;
Expand Down
12 changes: 12 additions & 0 deletions packages/taquito/src/wallet/operation-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { IncreasePaidStorageWalletOperation } from './increase-paid-storage-oper
import { WalletOperation } from './operation';
import { OriginationWalletOperation } from './origination-operation';
import { TransactionWalletOperation } from './transaction-operation';
import { TransferTicketWalletOperation } from './transfer-ticket-operation';
import { ConfirmationTimeoutError } from '../errors';

export function timeoutAfter<T>(timeoutMillisec: number): (source: Observable<T>) => Observable<T> {
Expand Down Expand Up @@ -132,6 +133,17 @@ export class OperationFactory {
);
}

async createTransferTicketOperation(
hash: string,
config: OperationFactoryConfig = {}
): Promise<TransferTicketWalletOperation> {
return new TransferTicketWalletOperation(
hash,
this.context.clone(),
await this.createHeadObservableFromConfig(config)
);
}

async createDelegationOperation(
hash: string,
config: OperationFactoryConfig = {}
Expand Down
54 changes: 54 additions & 0 deletions packages/taquito/src/wallet/transfer-ticket-operation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { WalletOperation, OperationStatus } from './operation';
import { Context } from '../context';
import { Observable } from 'rxjs';
import {
BlockResponse,
OpKind,
OperationContentsAndResultReveal,
OperationContentsAndResultTransferTicket,
} from '@taquito/rpc';
import { ObservableError } from './errors';

export class TransferTicketWalletOperation extends WalletOperation {
constructor(
public readonly opHash: string,
protected readonly context: Context,
newHead$: Observable<BlockResponse>
) {
super(opHash, context, newHead$);
}

public async revealOperation() {
const operationResult = await this.operationResults();
if (!operationResult) {
throw new ObservableError('operationResult returned undefined');
}

return operationResult.find((x) => x.kind === OpKind.REVEAL) as
| OperationContentsAndResultReveal
| undefined;
}

public async transferTicketOperation() {
const operationResult = await this.operationResults();
if (!operationResult) {
throw new ObservableError('operationResult returned undefined');
}
return operationResult.find((x) => x.kind === OpKind.TRANSFER_TICKET) as
| OperationContentsAndResultTransferTicket
| undefined;
}

public async status(): Promise<OperationStatus> {
if (!this._included) {
return 'pending';
}

const op = await this.transferTicketOperation();
if (!op) {
return 'unknown';
}

return op.metadata.operation_result.status;
}
}
37 changes: 36 additions & 1 deletion packages/taquito/src/wallet/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
WalletStakeParams,
WalletUnstakeParams,
WalletFinalizeUnstakeParams,
WalletTransferTicketParams,
} from './interface';
import {
InvalidAddressError,
Expand All @@ -43,7 +44,8 @@ export type WalletParamsWithKind =
| withKind<WalletTransferParams, OpKind.TRANSACTION>
| withKind<WalletOriginateParams, OpKind.ORIGINATION>
| withKind<WalletDelegateParams, OpKind.DELEGATION>
| withKind<WalletIncreasePaidStorageParams, OpKind.INCREASE_PAID_STORAGE>;
| withKind<WalletIncreasePaidStorageParams, OpKind.INCREASE_PAID_STORAGE>
| withKind<WalletTransferTicketParams, OpKind.TRANSFER_TICKET>;

export class WalletOperationBatch {
private operations: WalletParamsWithKind[] = [];
Expand Down Expand Up @@ -115,6 +117,19 @@ export class WalletOperationBatch {
return this;
}

/**
* @description Add an TransferTicket operation to the batch
* @param param TransferTicket operation parameter
*/
withTransferTicket(params: WalletTransferTicketParams) {
const destinationValidation = validateAddress(params.destination);
if (destinationValidation !== ValidationResult.VALID) {
throw new InvalidAddressError(params.destination, invalidDetail(destinationValidation));
}
this.operations.push({ kind: OpKind.TRANSFER_TICKET, ...params });
return this;
}

private async mapOperation(param: WalletParamsWithKind) {
switch (param.kind) {
case OpKind.TRANSACTION:
Expand Down Expand Up @@ -323,6 +338,26 @@ export class Wallet {
});
}

/**
* @description Transfer tezos tickets from current address to a specific address or a smart contract
* @returns a TransferTicketWalletOperation promise object when followed by .send()
* @param params operation parameter
*/
transferTicket(params: WalletTransferTicketParams) {
const toValidation = validateAddress(params.destination);
if (toValidation !== ValidationResult.VALID) {
throw new InvalidAddressError(params.destination, invalidDetail(toValidation));
}
return this.walletCommand(async () => {
const mappedParams = await this.walletProvider.mapTransferTicketParamsToWalletParams(
async () => params
);

const opHash = await this.walletProvider.sendOperations([mappedParams]);
return this.context.operationFactory.createTransferTicketOperation(opHash);
});
}

/**
* @description Stake a given amount for the source address
* @returns a TransactionWalletOperation promise object when followed by .send()
Expand Down

0 comments on commit dc9fafc

Please sign in to comment.