Skip to content

Commit c57d08a

Browse files
authored
Merge pull request #164 from Concordium/feature/sponsored-transactions
Feature/sponsored transactions
2 parents ecbf858 + b8a57b0 commit c57d08a

8 files changed

Lines changed: 207 additions & 128 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,10 @@ name: Build
22

33
on:
44
pull_request:
5-
branches:
6-
- main
7-
paths:
8-
- '.github/workflows/ci.yaml'
9-
- '**.hs'
10-
- 'stack*.yaml'
11-
- 'package.yaml'
12-
- 'fourmolu.yaml'
13-
- 'deps/concordium-client'
145

156
push:
167
branches:
178
- main
18-
paths:
19-
- '.github/workflows/ci.yaml'
20-
- '**.hs'
21-
- 'stack*.yaml'
22-
- 'package.yaml'
23-
- 'fourmolu.yaml'
24-
- 'deps/concordium-client'
259

2610
workflow_dispatch: # allow manual trigger
2711

ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## [unreleased]
44

5+
- Support for sponsored transactions for `/v0/submitTransfer` and `v3/accTransactions`.
6+
57
## [0.43.0] - 2025-11-21
68

79
- `/v0/submissionStatus` now supports RegisterData transactions.

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ cooldowns and the available balance) and get the info if an account is on any al
2323
of a transfer or credential deployment
2424
* `PUT /v0/submitCredential`: deploy a credential/create an account
2525
* `PUT /v0/submitTransfer`: perform a simple transfer
26+
* `PUT /v0/submitExtended`: perform an extended transfer
2627
* `PUT /v0/submitRawTransaction`: perform a any raw transaction
2728
* `GET /v0/accTransactions/{account address}`: get the transactions affecting an account's ccd balance
2829
* `GET /v1/accTransactions/{account address}`: get the transactions affecting an account's ccd balance (including CCD transactions with memos)
@@ -586,6 +587,32 @@ The data that should be sent is as the one returned from the library provided as
586587
After submission of the transaction the responses are the same as for the submission of the credential. If successful
587588
a submission id is returned, which can be used to query the status of the transfer via the `/v0/submissionStatus` endpoint.
588589

590+
## Submit extended transfer
591+
592+
When submitting an extended transfer (e.g. when the transaction is sponsored)
593+
you should make a PUT request to `/v0/submitExtended` endpoint. The JSON encoded
594+
transaction has the form:
595+
596+
```json
597+
{
598+
"signatures": {
599+
"sender": {
600+
"0" : {
601+
"0": "6f17c110965054b262ef0d6dee02f77dccb7bd031c2af324b544f5ee3e6e18b3fd1be8a95782e92a89dd40a1b69cad8a37e8b86fc9107c8528d8267212cf030b"
602+
}
603+
}
604+
"sponsor": {
605+
"0" : {
606+
"0": "6f17c110965054b262ef0d6dee02f77dccb7bd031c2af324b544f5ee3e6e18b3fd1be8a95782e92a89dd40a1b69cad8a37e8b86fc9107c8528d8267212cf030b"
607+
}
608+
609+
}
610+
},
611+
"transaction": "<base 16 encoded extended transaction>"
612+
```
613+
614+
If the submission was successful, a submission id is returned, which can be used to query the status
615+
of the transfer via the `/v0/submissionStatus` endpoint.
589616

590617
## Submit raw transaction
591618

@@ -630,6 +657,9 @@ They support the following parameters.
630657
- `y`: only include shield, unshield, and transfer shielded transactions.
631658
- `includeRawRejectReason`: whether to include the raw rejection reason (the
632659
same JSON as returned by `GetTransactionStatus` gRPC endpoint).
660+
- `includeSponsoredTransactions`: whether to include sponsored transactions.
661+
- `y`: include all sponsored transactions (The default).
662+
- `n`: exclude sponsored transactions.
633663

634664
The result is a JSON object with the following fields:
635665
- `order`: either `"ascending"` or `"descending"` indicating the ordering applied to the transactions.
@@ -788,6 +818,13 @@ It consists of the following fields:
788818
- The following field is present if the transaction is a register data transaction:
789819
- `registeredData`: hex encoding of the data that was registered
790820

821+
#### `sponsor` (optional)
822+
A JSON object containing details about the sponsor of a transaction.
823+
It consists of the following fields:
824+
825+
- `sponsor`: The account address of the sponsor.
826+
- `cost`: The transaction cost paid for by the sponsor.
827+
791828
For the purposes of the above, a simple transfer is a transaction of type `"transfer"` which transfers funds from one account to another.
792829
A transactions of type `"transfer"` is not considered a simple transfer if the destination is a smart contract instance.
793830
### Example
@@ -806,6 +843,10 @@ $ curl -XGET http://localhost:3000/v0/accTransactions/4KYJHs49FX7tPD2pFY2whbfZ8A
806843
},
807844
"energy": 59,
808845
"cost": 59,
846+
"sponsor": {
847+
"sponsor": "4KYJHs49FX7tPD2pFY2whbfZ8AjupEtX8yNSLwWMFQFUZgRobL",
848+
"cost": 59
849+
},
809850
"subtotal": 0,
810851
"transactionHash": "84bf1e2ef8d3af3063cdb681932990f71ddb3949655f55307a266e5d687b414f",
811852
"blockHash": "013c6d2dd67affd6f39b9a7b255d244055b53d68fe8b0add4839a20e911d04cb",

src/Internationalization.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ instance Internationalizable TransactionSummaryType where
2626
i18n i (TSTCredentialDeploymentTransaction t) = i18nDeployCredential i t
2727
i18n i (TSTUpdateTransaction t) = i18nUpdateTransaction i t
2828

29-
instance Internationalizable Event where
30-
i18n = i18nEvent
29+
instance Internationalizable SupplementedEvent where
30+
i18n = i18nSupplementedEvent
3131

3232
instance Internationalizable SpecialTransactionOutcome where
3333
i18n = i18nSpecialEvent

src/Internationalization/Base.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ data I18n = I18n
4747
i18nTransactionType :: TransactionType -> Text,
4848
i18nMalformedTransaction :: Text,
4949
i18nDeployCredential :: CredentialType -> Text,
50-
i18nEvent :: Event -> Text,
50+
i18nSupplementedEvent :: SupplementedEvent -> Text,
5151
i18nUpdateTransaction :: UpdateType -> Text,
5252
i18nSpecialEvent :: SpecialTransactionOutcome -> Text,
5353
i18nSpecialOutcomeShort :: SpecialTransactionOutcome -> Text,

src/Internationalization/En.hs

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ translation = I18n{..}
125125
i18nDeployCredential Initial = "Deploy initial account credential"
126126
i18nDeployCredential Normal = "Deploy account credential"
127127

128-
i18nEvent (ModuleDeployed mref) = "Deployed module " <> descrModule mref
129-
i18nEvent ContractInitialized{..} =
128+
i18nSupplementedEvent (ModuleDeployed mref) = "Deployed module " <> descrModule mref
129+
i18nSupplementedEvent ContractInitialized{..} =
130130
"Initialized smart contract "
131131
<> initContractName ecInitName
132132
<> " at address "
@@ -136,7 +136,7 @@ translation = I18n{..}
136136
<> ". "
137137
<> Text.pack (show (length ecEvents))
138138
<> " events were logged"
139-
i18nEvent Updated{..} =
139+
i18nSupplementedEvent Updated{..} =
140140
let (cname, fname) = contractAndFunctionName euReceiveName
141141
in "Invoked smart contract: source="
142142
<> descrAddress euInstigator
@@ -150,53 +150,53 @@ translation = I18n{..}
150150
<> descrAmount euAmount
151151
<> ", message="
152152
<> Text.pack (show euMessage)
153-
i18nEvent (Transferred sender amt recv) = "Transferred " <> descrAmount amt <> " from " <> descrAddress sender <> " to " <> descrAddress recv
154-
i18nEvent (AccountCreated addr) = "Created account with address " <> descrAccount addr
155-
i18nEvent (CredentialDeployed _ addr) = "Deployed a credential to account " <> descrAccount addr
156-
i18nEvent BakerAdded{..} = "Added validator " <> descrBaker ebaBakerId ebaAccount <> " and initial stake " <> descrAmount ebaStake
157-
i18nEvent BakerRemoved{..} = "Removed validator " <> descrBaker ebrBakerId ebrAccount
158-
i18nEvent BakerStakeIncreased{..} = "Stake of validator " <> descrBaker ebsiBakerId ebsiAccount <> " increased to " <> descrAmount ebsiNewStake
159-
i18nEvent BakerStakeDecreased{..} = "Stake of validator " <> descrBaker ebsiBakerId ebsiAccount <> " decreased to " <> descrAmount ebsiNewStake
160-
i18nEvent BakerSetRestakeEarnings{..} = "Validator " <> descrBaker ebsreBakerId ebsreAccount <> if ebsreRestakeEarnings then " set to restake earnings." else " unset restaking of earnings."
161-
i18nEvent BakerKeysUpdated{..} = "Validator " <> descrBaker ebkuBakerId ebkuAccount <> " keys updated."
162-
i18nEvent CredentialKeysUpdated{..} = "Updated keys of credential with ID " <> Text.pack (show ckuCredId)
163-
i18nEvent NewEncryptedAmount{..} = "New encrypted amount added to account " <> descrAccount neaAccount
164-
i18nEvent EncryptedAmountsRemoved{..} = "Consumed encrypted amounts on account " <> descrAccount earAccount
165-
i18nEvent EncryptedSelfAmountAdded{..} = "Updated shielded balance of account " <> descrAccount eaaAccount
166-
i18nEvent AmountAddedByDecryption{..} = "Unshielded " <> descrAmount aabdAmount <> " on account " <> descrAccount aabdAccount
167-
i18nEvent UpdateEnqueued{} = "Chain update event enqueued."
168-
i18nEvent TransferredWithSchedule{..} = "Transferred with schedule from " <> descrAccount etwsFrom <> " to " <> descrAccount etwsTo
169-
i18nEvent CredentialsUpdated{..} = "Credentials on account " <> descrAccount cuAccount <> " updated."
170-
i18nEvent DataRegistered{} = "Data registered on the chain."
171-
i18nEvent TransferMemo{..} = "Memo '" <> Text.pack (show tmMemo) <> "' included in a transfer." -- TODO: This would ideally try to render the Memo in a readable way, if it is a valid string or integer, say.
172-
i18nEvent Interrupted{..} = "Execution of " <> descrInstance iAddress <> " triggered an operation."
173-
i18nEvent Resumed{..} | rSuccess = "Operation succeeded and execution of " <> descrInstance rAddress <> " resumed."
174-
i18nEvent Resumed{..} | otherwise = "Operation failed and execution of " <> descrInstance rAddress <> " resumed."
175-
i18nEvent Upgraded{..} = "Smart contract instance at " <> descrInstance euAddress <> " was upgraded from " <> descrModule euFrom <> " to " <> descrModule euTo <> "."
176-
i18nEvent BakerSetOpenStatus{..} = "Open status of validator " <> descrBaker ebsosBakerId ebsosAccount <> " set to " <> descrOpenStatus ebsosOpenStatus
177-
i18nEvent BakerSetMetadataURL{..} = "Metadata URL of validator " <> descrBaker ebsmuBakerId ebsmuAccount <> " set to " <> descrMetadataURL ebsmuMetadataURL
178-
i18nEvent BakerSetTransactionFeeCommission{..} = "Transaction fee commission of validator " <> descrBaker ebstfcBakerId ebstfcAccount <> " set to " <> descrAmountFraction ebstfcTransactionFeeCommission
179-
i18nEvent BakerSetBakingRewardCommission{..} = "Block reward commission of validator " <> descrBaker ebsbrcBakerId ebsbrcAccount <> " set to " <> descrAmountFraction ebsbrcBakingRewardCommission
180-
i18nEvent BakerSetFinalizationRewardCommission{..} = "Finalization reward commission of validator " <> descrBaker ebsfrcBakerId ebsfrcAccount <> " set to " <> descrAmountFraction ebsfrcFinalizationRewardCommission
181-
i18nEvent DelegationStakeIncreased{..} = "Stake of delegator " <> descrDelegator edsiDelegatorId edsiAccount <> " increased to " <> descrAmount edsiNewStake
182-
i18nEvent DelegationStakeDecreased{..} = "Stake of delegator " <> descrDelegator edsdDelegatorId edsdAccount <> " decreased to " <> descrAmount edsdNewStake
183-
i18nEvent DelegationSetRestakeEarnings{..} = "Delegator " <> descrDelegator edsreDelegatorId edsreAccount <> if edsreRestakeEarnings then " set to restake earnings." else " unset restaking of earnings."
184-
i18nEvent DelegationSetDelegationTarget{..} =
153+
i18nSupplementedEvent (Transferred sender amt recv) = "Transferred " <> descrAmount amt <> " from " <> descrAddress sender <> " to " <> descrAddress recv
154+
i18nSupplementedEvent (AccountCreated addr) = "Created account with address " <> descrAccount addr
155+
i18nSupplementedEvent (CredentialDeployed _ addr) = "Deployed a credential to account " <> descrAccount addr
156+
i18nSupplementedEvent BakerAdded{..} = "Added validator " <> descrBaker ebaBakerId ebaAccount <> " and initial stake " <> descrAmount ebaStake
157+
i18nSupplementedEvent BakerRemoved{..} = "Removed validator " <> descrBaker ebrBakerId ebrAccount
158+
i18nSupplementedEvent BakerStakeIncreased{..} = "Stake of validator " <> descrBaker ebsiBakerId ebsiAccount <> " increased to " <> descrAmount ebsiNewStake
159+
i18nSupplementedEvent BakerStakeDecreased{..} = "Stake of validator " <> descrBaker ebsiBakerId ebsiAccount <> " decreased to " <> descrAmount ebsiNewStake
160+
i18nSupplementedEvent BakerSetRestakeEarnings{..} = "Validator " <> descrBaker ebsreBakerId ebsreAccount <> if ebsreRestakeEarnings then " set to restake earnings." else " unset restaking of earnings."
161+
i18nSupplementedEvent BakerKeysUpdated{..} = "Validator " <> descrBaker ebkuBakerId ebkuAccount <> " keys updated."
162+
i18nSupplementedEvent CredentialKeysUpdated{..} = "Updated keys of credential with ID " <> Text.pack (show ckuCredId)
163+
i18nSupplementedEvent NewEncryptedAmount{..} = "New encrypted amount added to account " <> descrAccount neaAccount
164+
i18nSupplementedEvent EncryptedAmountsRemoved{..} = "Consumed encrypted amounts on account " <> descrAccount earAccount
165+
i18nSupplementedEvent EncryptedSelfAmountAdded{..} = "Updated shielded balance of account " <> descrAccount eaaAccount
166+
i18nSupplementedEvent AmountAddedByDecryption{..} = "Unshielded " <> descrAmount aabdAmount <> " on account " <> descrAccount aabdAccount
167+
i18nSupplementedEvent UpdateEnqueued{} = "Chain update event enqueued."
168+
i18nSupplementedEvent TransferredWithSchedule{..} = "Transferred with schedule from " <> descrAccount etwsFrom <> " to " <> descrAccount etwsTo
169+
i18nSupplementedEvent CredentialsUpdated{..} = "Credentials on account " <> descrAccount cuAccount <> " updated."
170+
i18nSupplementedEvent DataRegistered{} = "Data registered on the chain."
171+
i18nSupplementedEvent TransferMemo{..} = "Memo '" <> Text.pack (show tmMemo) <> "' included in a transfer." -- TODO: This would ideally try to render the Memo in a readable way, if it is a valid string or integer, say.
172+
i18nSupplementedEvent Interrupted{..} = "Execution of " <> descrInstance iAddress <> " triggered an operation."
173+
i18nSupplementedEvent Resumed{..} | rSuccess = "Operation succeeded and execution of " <> descrInstance rAddress <> " resumed."
174+
i18nSupplementedEvent Resumed{..} | otherwise = "Operation failed and execution of " <> descrInstance rAddress <> " resumed."
175+
i18nSupplementedEvent Upgraded{..} = "Smart contract instance at " <> descrInstance euAddress <> " was upgraded from " <> descrModule euFrom <> " to " <> descrModule euTo <> "."
176+
i18nSupplementedEvent BakerSetOpenStatus{..} = "Open status of validator " <> descrBaker ebsosBakerId ebsosAccount <> " set to " <> descrOpenStatus ebsosOpenStatus
177+
i18nSupplementedEvent BakerSetMetadataURL{..} = "Metadata URL of validator " <> descrBaker ebsmuBakerId ebsmuAccount <> " set to " <> descrMetadataURL ebsmuMetadataURL
178+
i18nSupplementedEvent BakerSetTransactionFeeCommission{..} = "Transaction fee commission of validator " <> descrBaker ebstfcBakerId ebstfcAccount <> " set to " <> descrAmountFraction ebstfcTransactionFeeCommission
179+
i18nSupplementedEvent BakerSetBakingRewardCommission{..} = "Block reward commission of validator " <> descrBaker ebsbrcBakerId ebsbrcAccount <> " set to " <> descrAmountFraction ebsbrcBakingRewardCommission
180+
i18nSupplementedEvent BakerSetFinalizationRewardCommission{..} = "Finalization reward commission of validator " <> descrBaker ebsfrcBakerId ebsfrcAccount <> " set to " <> descrAmountFraction ebsfrcFinalizationRewardCommission
181+
i18nSupplementedEvent DelegationStakeIncreased{..} = "Stake of delegator " <> descrDelegator edsiDelegatorId edsiAccount <> " increased to " <> descrAmount edsiNewStake
182+
i18nSupplementedEvent DelegationStakeDecreased{..} = "Stake of delegator " <> descrDelegator edsdDelegatorId edsdAccount <> " decreased to " <> descrAmount edsdNewStake
183+
i18nSupplementedEvent DelegationSetRestakeEarnings{..} = "Delegator " <> descrDelegator edsreDelegatorId edsreAccount <> if edsreRestakeEarnings then " set to restake earnings." else " unset restaking of earnings."
184+
i18nSupplementedEvent DelegationSetDelegationTarget{..} =
185185
"Delegator "
186186
<> descrDelegator edsdtDelegatorId edsdtAccount
187187
<> " set delegation target to "
188188
<> case edsdtDelegationTarget of
189189
DelegatePassive -> "passive delegation"
190190
DelegateToBaker bid -> "staking pool " <> Text.pack (show bid)
191-
i18nEvent DelegationAdded{..} = "Added delegator " <> descrDelegator edaDelegatorId edaAccount
192-
i18nEvent DelegationRemoved{..} = "Removed delegator " <> descrDelegator edrDelegatorId edrAccount
193-
i18nEvent BakerSuspended{..} = "Validator " <> descrBaker ebsBakerId ebsAccount <> " was suspended."
194-
i18nEvent BakerResumed{..} = "Validator " <> descrBaker ebrBakerId ebrAccount <> " was resumed."
195-
i18nEvent (TokenModuleEvent tokenId type' _) = Text.pack (show tokenId) <> " token module event occurred of type " <> Text.pack (show type') <> "." -- TODO: It would be ideally to render the `details` in a readable way in the wallets.
196-
i18nEvent (TokenTransfer tokenId from to amount memo) = Text.pack (tokenAmountToString amount) <> " " <> Text.pack (show tokenId) <> " transferred from " <> Text.pack (show from) <> " to " <> Text.pack (show to) <> maybe "" (\m -> " with memo " <> Text.pack (show m)) memo <> "." -- TODO: It would be ideally to render the `memo` in a readable way in the wallets.
197-
i18nEvent TokenMint{..} = Text.pack (tokenAmountToString etmAmount) <> " " <> Text.pack (show etmTokenId) <> " minted to " <> Text.pack (show etmTarget) <> "."
198-
i18nEvent TokenBurn{..} = Text.pack (tokenAmountToString etbAmount) <> " " <> Text.pack (show etbTokenId) <> " burned from " <> Text.pack (show etbTarget) <> "."
199-
i18nEvent TokenCreated{..} = "Token created: " <> Text.pack (showPrettyJSON etcPayload)
191+
i18nSupplementedEvent DelegationAdded{..} = "Added delegator " <> descrDelegator edaDelegatorId edaAccount
192+
i18nSupplementedEvent DelegationRemoved{..} = "Removed delegator " <> descrDelegator edrDelegatorId edrAccount
193+
i18nSupplementedEvent BakerSuspended{..} = "Validator " <> descrBaker ebsBakerId ebsAccount <> " was suspended."
194+
i18nSupplementedEvent BakerResumed{..} = "Validator " <> descrBaker ebrBakerId ebrAccount <> " was resumed."
195+
i18nSupplementedEvent (TokenModuleEvent tokenId type' _) = Text.pack (show tokenId) <> " token module event occurred of type " <> Text.pack (show type') <> "." -- TODO: It would be ideally to render the `details` in a readable way in the wallets.
196+
i18nSupplementedEvent (TokenTransfer tokenId from to amount memo) = Text.pack (tokenAmountToString amount) <> " " <> Text.pack (show tokenId) <> " transferred from " <> Text.pack (show from) <> " to " <> Text.pack (show to) <> maybe "" (\m -> " with memo " <> Text.pack (show m)) memo <> "." -- TODO: It would be ideally to render the `memo` in a readable way in the wallets.
197+
i18nSupplementedEvent TokenMint{..} = Text.pack (tokenAmountToString etmAmount) <> " " <> Text.pack (show etmTokenId) <> " minted to " <> Text.pack (show etmTarget) <> "."
198+
i18nSupplementedEvent TokenBurn{..} = Text.pack (tokenAmountToString etbAmount) <> " " <> Text.pack (show etbTokenId) <> " burned from " <> Text.pack (show etbTarget) <> "."
199+
i18nSupplementedEvent TokenCreated{..} = "Token created: " <> Text.pack (showPrettyJSON etcPayload)
200200
i18nSpecialEvent BakingRewards{..} =
201201
"Block rewards\n"
202202
<> Text.unlines (map (\(addr, amnt) -> " - account " <> descrAccount addr <> " awarded " <> descrAmount amnt) . Map.toAscList . accountAmounts $ stoBakerRewards)

0 commit comments

Comments
 (0)