Skip to content

Commit

Permalink
Merge branch 'stellar:master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
celestialkylin committed Jun 12, 2024
2 parents ba29d60 + 840f57d commit 38ead87
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 13 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ A breaking change will get clearly marked in this log.

## Unreleased

### Added
- `contract.AssembledTransaction` now has a `toXDR` and `fromXDR` method for serializing the
transaction to and from XDR. Additionally, `contract.Client` now has a `txFromXDR`. These methods
should be used in place of `AssembledTransaction.toJSON`, `AssembledTransaction.fromJSON`, and
`Client.txFromJSON` for multi-auth signing. The JSON methods are now deprecated. **Note you must now
call `simulate` on the transaction before the final `signAndSend` call after all required signatures
are gathered when using the XDR methods.

### Deprecated
- In `contract.AssembledTransaction`, `toJSON` and `fromJSON` should be replaced with `toXDR` and
`fromXDR`. Similarly, in `contract.Client`, `txFromJSON` should be replaced with `txFromXDR`.


## [v12.0.1](https://github.com/stellar/js-stellar-sdk/compare/v11.3.0...v12.0.1)

Expand Down
58 changes: 51 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,47 @@ 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 operation = built.operations[0] as Operation.InvokeHostFunction;
if (!operation?.func?.value || typeof operation.func.value !== 'function') {
throw new Error("Could not extract the method from the transaction envelope.");
}
const invokeContractArgs = operation.func.value() as xdr.InvokeContractArgs;
if (!invokeContractArgs?.functionName) {
throw new Error("Could not extract the method name from the transaction envelope.");
}
const method = invokeContractArgs.functionName().toString('utf-8');
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 +454,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);

}

1 change: 1 addition & 0 deletions src/contract/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from "./rust_result";
export * from "./sent_transaction";
export * from "./spec";
export * from "./types";
export { DEFAULT_TIMEOUT } from "./utils";
13 changes: 7 additions & 6 deletions test/e2e/src/test-swap.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,31 +100,32 @@ describe("Swap Contract Tests", function () {
expect(needsNonInvokerSigningBy.indexOf(this.context.bob.publicKey())).to.equal(1, "needsNonInvokerSigningBy does not have bob's public key!");

// root serializes & sends to alice
const jsonFromRoot = tx.toJSON();
const xdrFromRoot = tx.toXDR();
const { client: clientAlice } = await clientFor("swap", {
keypair: this.context.alice,
contractId: this.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: this.context.bob,
contractId: this.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: this.context.root,
contractId: this.context.swapId,
});
const txRoot = clientRoot.txFromJSON(jsonFromBob);
const txRoot = clientRoot.txFromXDR(xdrFromBob);

await txRoot.simulate();
const result = await txRoot.signAndSend();

expect(result).to.have.property('sendTransactionResponse');
Expand Down

0 comments on commit 38ead87

Please sign in to comment.