-
Notifications
You must be signed in to change notification settings - Fork 9
[WAL-1471] Add support for sponsored transactions #659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
cf68097
82c7714
ba80854
50f2956
a9a53d2
789fe10
bbcf670
a2519f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,158 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| <!DOCTYPE html> | ||||||||||||||||||||||||||||||||||||||||||||||
| <html> | ||||||||||||||||||||||||||||||||||||||||||||||
| <head> | ||||||||||||||||||||||||||||||||||||||||||||||
| <title>My cool dapp</title> | ||||||||||||||||||||||||||||||||||||||||||||||
| <script src="/sdk.js"></script> | ||||||||||||||||||||||||||||||||||||||||||||||
| <script src="/helpers.js"></script> | ||||||||||||||||||||||||||||||||||||||||||||||
| <script src="https://unpkg.com/cbor-web"></script> | ||||||||||||||||||||||||||||||||||||||||||||||
| <meta charset="utf-8" /> | ||||||||||||||||||||||||||||||||||||||||||||||
| <script> | ||||||||||||||||||||||||||||||||||||||||||||||
| let currentAccountAddress = ''; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| async function submitPayloadToSponsor(sender, transaction) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const provider = await concordiumHelpers.detectConcordiumProvider(); | ||||||||||||||||||||||||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||||||||||||||||||||||||
| buildBasicAccountSigner, | ||||||||||||||||||||||||||||||||||||||||||||||
| AccountAddress, | ||||||||||||||||||||||||||||||||||||||||||||||
| ConcordiumGRPCClient, | ||||||||||||||||||||||||||||||||||||||||||||||
| Transaction, | ||||||||||||||||||||||||||||||||||||||||||||||
| TransactionExpiry, | ||||||||||||||||||||||||||||||||||||||||||||||
| } = concordiumSDK; | ||||||||||||||||||||||||||||||||||||||||||||||
| const builder = Transaction.builderFromJSON(transaction); | ||||||||||||||||||||||||||||||||||||||||||||||
| const sponsorSigner = buildBasicAccountSigner(privateKey.value); | ||||||||||||||||||||||||||||||||||||||||||||||
| const sponsorSignerAccount = AccountAddress.fromBase58(sponsorAccount.value); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const grpcClient = new ConcordiumGRPCClient(await provider.grpcTransport); | ||||||||||||||||||||||||||||||||||||||||||||||
| const senderNonce = await grpcClient.getNextAccountNonce(sender); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const sponsorableTransaction = builder | ||||||||||||||||||||||||||||||||||||||||||||||
| .addMetadata({ sender, nonce: senderNonce.nonce, expiry: TransactionExpiry.futureMinutes(5) }) | ||||||||||||||||||||||||||||||||||||||||||||||
| .addSponsor(sponsorSignerAccount) | ||||||||||||||||||||||||||||||||||||||||||||||
| .build(); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const sponsored = await Transaction.sponsor(sponsorableTransaction, sponsorSigner); | ||||||||||||||||||||||||||||||||||||||||||||||
| return Transaction.toJSON(sponsored); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| async function setupPage() { | ||||||||||||||||||||||||||||||||||||||||||||||
| const provider = await concordiumHelpers.detectConcordiumProvider(); | ||||||||||||||||||||||||||||||||||||||||||||||
| provider.on('accountDisconnected', () => (currentAccountAddress = undefined)); | ||||||||||||||||||||||||||||||||||||||||||||||
| provider.on('accountChanged', (accountAddress) => (currentAccountAddress = accountAddress)); | ||||||||||||||||||||||||||||||||||||||||||||||
| provider.on('chainChanged', (chain) => alert(chain)); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| document.getElementById('connect').addEventListener('click', () => { | ||||||||||||||||||||||||||||||||||||||||||||||
| provider.connect().then((accountAddress) => { | ||||||||||||||||||||||||||||||||||||||||||||||
| currentAccountAddress = accountAddress; | ||||||||||||||||||||||||||||||||||||||||||||||
| document.getElementById('accountAddress').innerHTML = accountAddress; | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| document.getElementById('requestAccounts').addEventListener('click', () => { | ||||||||||||||||||||||||||||||||||||||||||||||
| provider.requestAccounts().then((accountAddresses) => { | ||||||||||||||||||||||||||||||||||||||||||||||
| currentAccountAddress = accountAddresses[0]; | ||||||||||||||||||||||||||||||||||||||||||||||
| document.getElementById('accountAddress').innerHTML = accountAddresses; | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| document.getElementById('signSimpleTransfer').addEventListener('click', async () => { | ||||||||||||||||||||||||||||||||||||||||||||||
| const { AccountAddress, CcdAmount, Transaction } = concordiumSDK; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const payload = { | ||||||||||||||||||||||||||||||||||||||||||||||
| amount: CcdAmount.fromCcd(1000n), | ||||||||||||||||||||||||||||||||||||||||||||||
| toAddress: AccountAddress.fromBase58(recipient.value), | ||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const transaction = Transaction.transfer(payload); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const sponsorResponse = await submitPayloadToSponsor( | ||||||||||||||||||||||||||||||||||||||||||||||
| AccountAddress.fromBase58(currentAccountAddress), | ||||||||||||||||||||||||||||||||||||||||||||||
| Transaction.toJSON(transaction) | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| console.log('sponsorResponse', sponsorResponse); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| return provider | ||||||||||||||||||||||||||||||||||||||||||||||
| .sendSponsoredTransaction(currentAccountAddress, 3, sponsorResponse) | ||||||||||||||||||||||||||||||||||||||||||||||
| .then((sig) => alert(JSON.stringify(sig))) | ||||||||||||||||||||||||||||||||||||||||||||||
| .catch(alert); | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| document.getElementById('signTokenUpdate').addEventListener('click', async () => { | ||||||||||||||||||||||||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||||||||||||||||||||||||
| AccountAddress, | ||||||||||||||||||||||||||||||||||||||||||||||
| TokenOperationType, | ||||||||||||||||||||||||||||||||||||||||||||||
| TokenAmount, | ||||||||||||||||||||||||||||||||||||||||||||||
| CborMemo, | ||||||||||||||||||||||||||||||||||||||||||||||
| Cbor, | ||||||||||||||||||||||||||||||||||||||||||||||
| TokenId, | ||||||||||||||||||||||||||||||||||||||||||||||
| Transaction, | ||||||||||||||||||||||||||||||||||||||||||||||
| CborAccountAddress, | ||||||||||||||||||||||||||||||||||||||||||||||
| } = concordiumSDK; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const ops = [ | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| [TokenOperationType.Transfer]: { | ||||||||||||||||||||||||||||||||||||||||||||||
| amount: TokenAmount.fromJSON({ | ||||||||||||||||||||||||||||||||||||||||||||||
| value: '1000000', | ||||||||||||||||||||||||||||||||||||||||||||||
| decimals: 6, | ||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||
| recipient: CborAccountAddress.fromAccountAddress( | ||||||||||||||||||||||||||||||||||||||||||||||
| AccountAddress.fromBase58(recipient.value) | ||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||
| memo: CborMemo.fromString('Some text for memo'), | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| console.log(JSON.stringify(ops)); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const payload = { | ||||||||||||||||||||||||||||||||||||||||||||||
| tokenId: TokenId.fromString('EURtest'), | ||||||||||||||||||||||||||||||||||||||||||||||
| operations: Cbor.encode(ops), | ||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const transaction = Transaction.tokenUpdate(payload); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| console.log(JSON.stringify(payload)); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const sponsorResponse = await submitPayloadToSponsor( | ||||||||||||||||||||||||||||||||||||||||||||||
| AccountAddress.fromBase58(currentAccountAddress), | ||||||||||||||||||||||||||||||||||||||||||||||
| Transaction.toJSON(transaction) | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| console.log('sponsorResponse', sponsorResponse); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| return provider | ||||||||||||||||||||||||||||||||||||||||||||||
| .sendSponsoredTransaction(currentAccountAddress, 27, sponsorResponse) | ||||||||||||||||||||||||||||||||||||||||||||||
| .then((sig) => alert(JSON.stringify(sig))) | ||||||||||||||||||||||||||||||||||||||||||||||
| .catch(alert); | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
120
to
132
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And here
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| setupPage(); | ||||||||||||||||||||||||||||||||||||||||||||||
| </script> | ||||||||||||||||||||||||||||||||||||||||||||||
| </head> | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| <body> | ||||||||||||||||||||||||||||||||||||||||||||||
| <div> | ||||||||||||||||||||||||||||||||||||||||||||||
| <button id="connect">Connect</button> | ||||||||||||||||||||||||||||||||||||||||||||||
| <h3 id="accountAddress" style="display: inline">Account address:</h3> | ||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||
| <br /> | ||||||||||||||||||||||||||||||||||||||||||||||
| <button id="requestAccounts">Request accounts</button> | ||||||||||||||||||||||||||||||||||||||||||||||
| <br /> | ||||||||||||||||||||||||||||||||||||||||||||||
| <h3>Sponsor Config:</h3> | ||||||||||||||||||||||||||||||||||||||||||||||
| Sponsor Account: | ||||||||||||||||||||||||||||||||||||||||||||||
| <input type="text" id="sponsorAccount" value="3PCRkKoFrSzgUmzfFF7C17pc3wm9wrVgbaCrbgGs6UMxy5aogo" /> | ||||||||||||||||||||||||||||||||||||||||||||||
| <br /> | ||||||||||||||||||||||||||||||||||||||||||||||
| Sponsor Private Key: | ||||||||||||||||||||||||||||||||||||||||||||||
| <input type="text" id="privateKey" value="9a494111614cd737ed89e500a3d155af80a4f8faf18f168568f8facbd2be3909" /> | ||||||||||||||||||||||||||||||||||||||||||||||
| <br /> | ||||||||||||||||||||||||||||||||||||||||||||||
| <h3>Recipient Config:</h3> | ||||||||||||||||||||||||||||||||||||||||||||||
| Recipient Address: | ||||||||||||||||||||||||||||||||||||||||||||||
| <input type="text" id="recipient" value="4jPwPo6da7g43DRQFcwMxJQQA9BbD762fbSS24X8Z7VHkvnehe" /> | ||||||||||||||||||||||||||||||||||||||||||||||
| <br /> | ||||||||||||||||||||||||||||||||||||||||||||||
| <br /> | ||||||||||||||||||||||||||||||||||||||||||||||
| <button id="signSimpleTransfer">Sign Simple Transfer</button> | ||||||||||||||||||||||||||||||||||||||||||||||
| <button id="signTokenUpdate">Sign PLT Transfer</button> | ||||||||||||||||||||||||||||||||||||||||||||||
| </body> | ||||||||||||||||||||||||||||||||||||||||||||||
| </html> | ||||||||||||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be good to create a
The release workflow is untested currently, so if the release job fails we need to look into a fix. |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -25,6 +25,7 @@ import type { | |||||||
| UpdateContractInput, | ||||||||
| UpdateCredentialsInput, | ||||||||
| VerifiablePresentation, | ||||||||
| Transaction, | ||||||||
| } from '@concordium/web-sdk'; | ||||||||
| import type { RpcTransport } from '@protobuf-ts/runtime-rpc'; | ||||||||
| import { LaxNumberEnumValue, LaxStringEnumValue } from './util'; | ||||||||
|
|
@@ -69,6 +70,8 @@ export type SendTransactionPayload = | |||||||
| | SendTransactionUpdateContractPayload | ||||||||
| | SendTransactionInitContractPayload; | ||||||||
|
|
||||||||
| export type SignableTransaction = Transaction.Signable; | ||||||||
|
|
||||||||
| export type SmartContractParameters = | ||||||||
| | { [key: string]: SmartContractParameters } | ||||||||
| | SmartContractParameters[] | ||||||||
|
|
@@ -254,6 +257,19 @@ interface MainWalletApi { | |||||||
| type: LaxNumberEnumValue<AccountTransactionType.ConfigureDelegation>, | ||||||||
| payload: ConfigureDelegationPayload | ||||||||
| ): Promise<string>; | ||||||||
| /** | ||||||||
| * Sends a transaction signed by sponsor to the Concordium Wallet and awaits the users action. | ||||||||
| * Note that a header is sent, and constructed by the sponsor. | ||||||||
| * Note that if the user rejects signing the transaction, this will throw an error. | ||||||||
| * @param accountAddress the address of the account that should sign the transaction | ||||||||
| * @param type the type of transaction that is to be signed and sent. | ||||||||
| * @param payload the sponsored transaction with header to be signed and sent. | ||||||||
| */ | ||||||||
| sendSponsoredTransaction( | ||||||||
| accountAddress: AccountAddressSource, | ||||||||
| type: LaxNumberEnumValue<AccountTransactionType.Transfer>, | ||||||||
| payload: SignableTransaction | ||||||||
|
||||||||
| type: LaxNumberEnumValue<AccountTransactionType.Transfer>, | |
| payload: SignableTransaction | |
| payload: SignableTransaction |
See
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,6 +2,8 @@ | |||||||||
|
|
||||||||||
| ## Unreleased | ||||||||||
|
|
||||||||||
| - Added support for Sponsored Transactions handling. With new method `sendSponsoredTransaction` in wallet-api. | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| ## 2.7.0 | ||||||||||
|
|
||||||||||
| ### Changed | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And consequently