Skip to main content

URI Scheme to facilitate delegated signing

info

This guide is available on three different programming languages: Typescript, Kotlin and Flutter (Dart). You can change the shown version on each page via the buttons above.

The Sep-7 standard defines a way for a non-wallet application to construct a URI scheme that represents a specific transaction for an account to sign. The scheme used is web+stellar, followed by a colon. Example: web+stellar:<operation>?<param1>=<value1>&<param2>=<value2>

Tx Operation​

The tx operation represents a request to sign a specific transaction envelope, with some configurable parameters.

const sourceAccountKeyPair = "G...";
const destinationAccountKeyPair = "G...";
const txBuilder = await stellar.transaction({
sourceAddress: sourceAccountKeyPair,
});
const tx = txBuilder.createAccount(destinationAccountKeyPair).build();
const xdr = encodeURIComponent(tx.toEnvelope().toXDR().toString("base64"));
const callback = encodeURIComponent("https://example.com/callback");
const txUri = `web+stellar:tx?xdr=${xdr}&callback=${callback}`;
const uri = wallet.parseSep7Uri(txUri);
// uri can be parsed and transaction can be signed/submitted by an application that implements Sep-7

You can set replacements to be made in the xdr for specific fields by the application, these will be added in the Sep-11 transaction representation format to the URI.

const uri = new Sep7Tx(txUri);
uri.addReplacement({
id: "X",
path: "sourceAccount",
hint: "account from where you want to pay fees",
});

You can assign parameters after creating the initial instance using the appropriate setter for the parameter.

const sourceAccountKeyPair = "G...";
const destinationAccountKeyPair = "G...";
const txBuilder = await stellar.transaction({
sourceAddress: sourceAccountKeyPair,
});
const tx = txBuilder.createAccount(destinationAccountKeyPair).build();
const uri = wallet.Sep7Tx.forTransaction(tx);
uri.callback = "https://example.com/callback";
uri.msg = "here goes a message";
uri.toString(); // encodes everything and converts to a uri string

Pay Operation​

The pay operation represents a request to pay a specific address with a specific asset, regardless of the source asset used by the payer. You can configure parameters to build the payment operation.

const destination = "G...";
const assetIssuer = "G...";
const assetCode = "USDC";
const amount = "120.1234567";
const memo = "memo";
const message = encodeURIComponent("pay me with lumens");
const originDomain = "example.com";
const payUri = `web+stellar:pay?destination=${destination}&amount=${amount}&memo=${memo}&msg=${message}&origin_domain=${originDomain}&asset_issuer=${assetIssuer}&asset_code=${assetCode}`;
const uri = parseSep7Uri(payUri);
// uri can be parsed and transaction can be built/signed/submitted by an application that implements Sep-7

You can assign parameters after creating the initial instance using the appropriate setter for the parameter.

const uri = wallet.Sep7Pay.forDestination("G...");
uri.callback = "https://example.com/callback";
uri.msg = "here goes a message";
uri.assetCode = "USDC";
uri.assetIssuer = "G...";
uri.amount = "10";
uri.toString(); // encodes everything and converts to a uri string

The last step after building a Sep7Tx or Sep7Pay is to add a signature to your uri. This will create a payload out of the transaction and sign it with the provided keypair.

const uri = wallet.Sep7Pay.forDestination("G...");
uri.originDomain = "example.com";
const keypair = wallet.stellar().account().createKeypair();
uri.addSignature(Keypair.fromSecret(keypair.secretKey));
console.log(uri.signature); // signed uri payload

The signature can then be verified by fetching the Stellar toml file from the origin domain in the uri, and using the included signing key to verify the uri signature. This is all done as part of the verifySignature method.

const passesVerification = await uri.verifySignature(); // true or false