Skip to content

Commit

Permalink
add toXDR and fromXDR for multiauth flow
Browse files Browse the repository at this point in the history
  • Loading branch information
BlaineHeffron committed May 30, 2024
1 parent 1b6d7aa commit af03cac
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 14 deletions.
51 changes: 44 additions & 7 deletions src/contract/assembled_transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
implementsToString,
} from "./utils";
import { SentTransaction } from "./sent_transaction";
import { Spec } from "./spec";

export const NULL_ACCOUNT =
"GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF";
Expand Down Expand Up @@ -364,6 +365,40 @@ export class AssembledTransaction<T> {
return txn;
}

/**
* Serialize the AssembledTransaction to a base64-encoded XDR string.
*/
toXDR(): string {
if(!this.built) throw new Error(
"Transaction has not yet been simulated; " +
"call `AssembledTransaction.simulate` first.",
);
return this.built?.toEnvelope().toXDR('base64');
}

/**
* Deserialize the AssembledTransaction from a base64-encoded XDR string.
*/
static fromXDR<T>(
options: Omit<AssembledTransactionOptions<T>, "args" | "method" | "parseResultXdr">,
encodedXDR: string,
spec: Spec
): AssembledTransaction<T> {
const envelope = xdr.TransactionEnvelope.fromXDR(encodedXDR, "base64");
const built = TransactionBuilder.fromXDR(envelope, options.networkPassphrase) as Tx;
const method = ((built.operations[0] as Operation.InvokeHostFunction).func.value() as xdr.InvokeContractArgs).functionName().toString('utf-8');
console.log(`method name is ${method}`);
const txn = new AssembledTransaction(
{ ...options,
method,
parseResultXdr: (result: xdr.ScVal) =>
spec.funcResToNative(method, result),
}
);
txn.built = built;
return txn;
}

private constructor(public options: AssembledTransactionOptions<T>) {
this.options.simulate = this.options.simulate ?? true;
this.server = new Server(this.options.rpcUrl, {
Expand Down Expand Up @@ -412,14 +447,16 @@ export class AssembledTransaction<T> {
}

simulate = async (): Promise<this> => {
if (!this.raw) {
throw new Error(
"Transaction has not yet been assembled; " +
"call `AssembledTransaction.build` first.",
);
}
if(!this.built){
if (!this.raw) {
throw new Error(
"Transaction has not yet been assembled; " +
"call `AssembledTransaction.build` first.",
);
}

this.built = this.raw.build();
this.built = this.raw.build();
}
this.simulation = await this.server.simulateTransaction(this.built);

if (Api.isSimulationSuccess(this.simulation)) {
Expand Down
3 changes: 3 additions & 0 deletions src/contract/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,8 @@ export class Client {
tx,
);
};

txFromXDR = <T>(xdrBase64: string): AssembledTransaction<T> => AssembledTransaction.fromXDR(this.options, xdrBase64, this.spec);

}

15 changes: 8 additions & 7 deletions test/e2e/src/test-swap.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,32 +104,33 @@ test("alice swaps bob 10 A for 1 B", async (t) => {
);

// root serializes & sends to alice
const jsonFromRoot = tx.toJSON();
const xdrFromRoot = tx.toXDR();
const { client: clientAlice } = await clientFor("swap", {
keypair: t.context.alice,
contractId: t.context.swapId,
});
const txAlice = clientAlice.txFromJSON(jsonFromRoot);
const txAlice = clientAlice.txFromXDR(xdrFromRoot);
await txAlice.signAuthEntries();

// alice serializes & sends to bob
const jsonFromAlice = txAlice.toJSON();
const xdrFromAlice = txAlice.toXDR();
const { client: clientBob } = await clientFor("swap", {
keypair: t.context.bob,
contractId: t.context.swapId,
});
const txBob = clientBob.txFromJSON(jsonFromAlice);
const txBob = clientBob.txFromXDR(xdrFromAlice);
await txBob.signAuthEntries();

// bob serializes & sends back to root
const jsonFromBob = txBob.toJSON();
const xdrFromBob = txBob.toXDR();
const { client: clientRoot } = await clientFor("swap", {
keypair: t.context.root,
contractId: t.context.swapId,
});
const txRoot = clientRoot.txFromJSON(jsonFromBob);
const txRoot = clientRoot.txFromXDR(xdrFromBob);

const result = await txRoot.signAndSend();
await txRoot.simulate();
const result = await txRoot.signAndSend({force: true});

t.truthy(
result.sendTransactionResponse,
Expand Down

0 comments on commit af03cac

Please sign in to comment.