Repository: hyperledger/firefly
Pull request #879 (2022-06-24 15:03:31)

surface URI as parameter for token mint
These changes also include added an optional `config` parameter, that is passed to directly to the token connectors without validation. 

codecov-commenter: # [Codecov](https://codecov.io/gh/hyperledger/firefly/pull/879?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger) Report
> Merging [#879](https://codecov.io/gh/hyperledger/firefly/pull/879?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger) (fa5f8f0) into [main](https://codecov.io/gh/hyperledger/firefly/commit/cf843bce3814611864702a8ee8f8a8cc3d102c1b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger) (cf843bc) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

```diff
@@           Coverage Diff           @@
##             main     #879   +/-   ##
=======================================
  Coverage   99.95%   99.95%           
=======================================
  Files         300      300           
  Lines       19479    19480    +1     
=======================================
+ Hits        19470    19472    +2     
+ Misses          7        6    -1     
  Partials        2        2           
```


| [Impacted Files](https://codecov.io/gh/hyperledger/firefly/pull/879?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger) | Coverage Δ | |
|---|---|---|
| [internal/tokens/fftokens/fftokens.go](https://codecov.io/gh/hyperledger/firefly/pull/879/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger#diff-aW50ZXJuYWwvdG9rZW5zL2ZmdG9rZW5zL2ZmdG9rZW5zLmdv) | `99.55% <100.00%> (+0.66%)` | :arrow_up: |
| [internal/apiserver/server.go](https://codecov.io/gh/hyperledger/firefly/pull/879/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger#diff-aW50ZXJuYWwvYXBpc2VydmVyL3NlcnZlci5nbw==) | `98.98% <0.00%> (-1.02%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/hyperledger/firefly/pull/879?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/hyperledger/firefly/pull/879?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger). Last update [cf843bc...fa5f8f0](https://codecov.io/gh/hyperledger/firefly/pull/879?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperledger).


Patch:
diff --git a/docs/reference/types/tokentransfer.md b/docs/reference/types/tokentransfer.md
index d97c4bbbc..0079b8272 100644
--- a/docs/reference/types/tokentransfer.md
+++ b/docs/reference/types/tokentransfer.md
@@ -66,6 +66,7 @@ nav_order: 11
 | `created` | The creation time of the transfer | [`FFTime`](simpletypes#fftime) |
 | `tx` | If submitted via FireFly, this will reference the UUID of the FireFly transaction (if the token connector in use supports attaching data) | [`TransactionRef`](#transactionref) |
 | `blockchainEvent` | The UUID of the blockchain event | [`UUID`](simpletypes#uuid) |
+| `config` | Input only field, with token connector specific configuration of the transfer. See your chosen token connector documentation for details | [`JSONObject`](simpletypes#jsonobject) |
 
 ## TransactionRef
 
diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml
index f5910d902..4f83b36c3 100644
--- a/docs/swagger/swagger.yaml
+++ b/docs/swagger/swagger.yaml
@@ -22785,6 +22785,15 @@ paths:
                     For example, with 18 decimals a fractional balance of 10.234 will
                     be specified as 10,234,000,000,000,000,000
                   type: string
+                config:
+                  additionalProperties:
+                    description: Input only field, with token connector specific configuration
+                      of the transfer. See your chosen token connector documentation
+                      for details
+                  description: Input only field, with token connector specific configuration
+                    of the transfer. See your chosen token connector documentation
+                    for details
+                  type: object
                 from:
                   description: The source account for the transfer. On input defaults
                     to the value of 'key'
@@ -22940,6 +22949,9 @@ paths:
                   description: The index of the token within the pool that this transfer
                     applies to
                   type: string
+                uri:
+                  description: The URI of the token this transfer applies to
+                  type: string
               type: object
       responses:
         "200":
@@ -23211,6 +23223,15 @@ paths:
                     For example, with 18 decimals a fractional balance of 10.234 will
                     be specified as 10,234,000,000,000,000,000
                   type: string
+                config:
+                  additionalProperties:
+                    description: Input only field, with token connector specific configuration
+                      of the transfer. See your chosen token connector documentation
+                      for details
+                  description: Input only field, with token connector specific configuration
+                    of the transfer. See your chosen token connector documentation
+                    for details
+                  type: object
                 from:
                   description: The source account for the transfer. On input defaults
                     to the value of 'key'
@@ -23366,6 +23387,9 @@ paths:
                   description: The index of the token within the pool that this transfer
                     applies to
                   type: string
+                uri:
+                  description: The URI of the token this transfer applies to
+                  type: string
               type: object
       responses:
         "200":
@@ -24415,6 +24439,15 @@ paths:
                     For example, with 18 decimals a fractional balance of 10.234 will
                     be specified as 10,234,000,000,000,000,000
                   type: string
+                config:
+                  additionalProperties:
+                    description: Input only field, with token connector specific configuration
+                      of the transfer. See your chosen token connector documentation
+                      for details
+                  description: Input only field, with token connector specific configuration
+                    of the transfer. See your chosen token connector documentation
+                    for details
+                  type: object
                 from:
                   description: The source account for the transfer. On input defaults
                     to the value of 'key'
@@ -24570,6 +24603,9 @@ paths:
                   description: The index of the token within the pool that this transfer
                     applies to
                   type: string
+                uri:
+                  description: The URI of the token this transfer applies to
+                  type: string
               type: object
       responses:
         "200":
@@ -30126,6 +30162,15 @@ paths:
                     For example, with 18 decimals a fractional balance of 10.234 will
                     be specified as 10,234,000,000,000,000,000
                   type: string
+                config:
+                  additionalProperties:
+                    description: Input only field, with token connector specific configuration
+                      of the transfer. See your chosen token connector documentation
+                      for details
+                  description: Input only field, with token connector specific configuration
+                    of the transfer. See your chosen token connector documentation
+                    for details
+                  type: object
                 from:
                   description: The source account for the transfer. On input defaults
                     to the value of 'key'
@@ -30277,6 +30322,9 @@ paths:
                   description: The index of the token within the pool that this transfer
                     applies to
                   type: string
+                uri:
+                  description: The URI of the token this transfer applies to
+                  type: string
               type: object
       responses:
         "200":
@@ -30534,6 +30582,15 @@ paths:
                     For example, with 18 decimals a fractional balance of 10.234 will
                     be specified as 10,234,000,000,000,000,000
                   type: string
+                config:
+                  additionalProperties:
+                    description: Input only field, with token connector specific configuration
+                      of the transfer. See your chosen token connector documentation
+                      for details
+                  description: Input only field, with token connector specific configuration
+                    of the transfer. See your chosen token connector documentation
+                    for details
+                  type: object
                 key:
                   description: The blockchain signing key for the transfer. On input
                     defaults to the first signing key of the organization that operates
@@ -30685,6 +30742,9 @@ paths:
                   description: The index of the token within the pool that this transfer
                     applies to
                   type: string
+                uri:
+                  description: The URI of the token this transfer applies to
+                  type: string
               type: object
       responses:
         "200":
@@ -31699,6 +31759,15 @@ paths:
                     For example, with 18 decimals a fractional balance of 10.234 will
                     be specified as 10,234,000,000,000,000,000
                   type: string
+                config:
+                  additionalProperties:
+                    description: Input only field, with token connector specific configuration
+                      of the transfer. See your chosen token connector documentation
+                      for details
+                  description: Input only field, with token connector specific configuration
+                    of the transfer. See your chosen token connector documentation
+                    for details
+                  type: object
                 from:
                   description: The source account for the transfer. On input defaults
                     to the value of 'key'
@@ -31854,6 +31923,9 @@ paths:
                   description: The index of the token within the pool that this transfer
                     applies to
                   type: string
+                uri:
+                  description: The URI of the token this transfer applies to
+                  type: string
               type: object
       responses:
         "200":
diff --git a/internal/coremsgs/en_struct_descriptions.go b/internal/coremsgs/en_struct_descriptions.go
index cfebd196f..7fb464421 100644
--- a/internal/coremsgs/en_struct_descriptions.go
+++ b/internal/coremsgs/en_struct_descriptions.go
@@ -565,6 +565,7 @@ var (
 	TokenTransferCreated         = ffm("TokenTransfer.created", "The creation time of the transfer")
 	TokenTransferTX              = ffm("TokenTransfer.tx", "If submitted via FireFly, this will reference the UUID of the FireFly transaction (if the token connector in use supports attaching data)")
 	TokenTransferBlockchainEvent = ffm("TokenTransfer.blockchainEvent", "The UUID of the blockchain event")
+	TokenTransferConfig          = ffm("TokenTransfer.config", "Input only field, with token connector specific configuration of the transfer. See your chosen token connector documentation for details")
 
 	// TokenTransferInput field descriptions
 	TokenTransferInputMessage = ffm("TokenTransferInput.message", "You can specify a message to correlate with the transfer, which can be of type broadcast or private. Your chosen token connector and on-chain smart contract must support on-chain/off-chain correlation by taking a `data` input on the transfer")
diff --git a/internal/tokens/fftokens/fftokens.go b/internal/tokens/fftokens/fftokens.go
index ec423492e..80686d0e6 100644
--- a/internal/tokens/fftokens/fftokens.go
+++ b/internal/tokens/fftokens/fftokens.go
@@ -147,34 +147,38 @@ type activatePool struct {
 }
 
 type mintTokens struct {
-	PoolLocator string `json:"poolLocator"`
-	TokenIndex  string `json:"tokenIndex,omitempty"`
-	To          string `json:"to"`
-	Amount      string `json:"amount"`
-	RequestID   string `json:"requestId,omitempty"`
-	Signer      string `json:"signer"`
-	Data        string `json:"data,omitempty"`
+	PoolLocator string             `json:"poolLocator"`
+	TokenIndex  string             `json:"tokenIndex,omitempty"`
+	To          string             `json:"to"`
+	Amount      string             `json:"amount"`
+	RequestID   string             `json:"requestId,omitempty"`
+	Signer      string             `json:"signer"`
+	Data        string             `json:"data,omitempty"`
+	URI         string             `json:"uri,omitempty"`
+	Config      fftypes.JSONObject `json:"config"`
 }
 
 type burnTokens struct {
-	PoolLocator string `json:"poolLocator"`
-	TokenIndex  string `json:"tokenIndex,omitempty"`
-	From        string `json:"from"`
-	Amount      string `json:"amount"`
-	RequestID   string `json:"requestId,omitempty"`
-	Signer      string `json:"signer"`
-	Data        string `json:"data,omitempty"`
+	PoolLocator string             `json:"poolLocator"`
+	TokenIndex  string             `json:"tokenIndex,omitempty"`
+	From        string             `json:"from"`
+	Amount      string             `json:"amount"`
+	RequestID   string             `json:"requestId,omitempty"`
+	Signer      string             `json:"signer"`
+	Data        string             `json:"data,omitempty"`
+	Config      fftypes.JSONObject `json:"config"`
 }
 
 type transferTokens struct {
-	PoolLocator string `json:"poolLocator"`
-	TokenIndex  string `json:"tokenIndex,omitempty"`
-	From        string `json:"from"`
-	To          string `json:"to"`
-	Amount      string `json:"amount"`
-	RequestID   string `json:"requestId,omitempty"`
-	Signer      string `json:"signer"`
-	Data        string `json:"data,omitempty"`
+	PoolLocator string             `json:"poolLocator"`
+	TokenIndex  string             `json:"tokenIndex,omitempty"`
+	From        string             `json:"from"`
+	To          string             `json:"to"`
+	Amount      string             `json:"amount"`
+	RequestID   string             `json:"requestId,omitempty"`
+	Signer      string             `json:"signer"`
+	Data        string             `json:"data,omitempty"`
+	Config      fftypes.JSONObject `json:"config"`
 }
 
 type tokenApproval struct {
@@ -663,6 +667,8 @@ func (ft *FFTokens) MintTokens(ctx context.Context, nsOpID string, poolLocator s
 			RequestID:   nsOpID,
 			Signer:      mint.Key,
 			Data:        string(data),
+			URI:         mint.URI,
+			Config:      mint.Config,
 		}).
 		SetError(&errRes).
 		Post("/api/v1/mint")
@@ -689,6 +695,7 @@ func (ft *FFTokens) BurnTokens(ctx context.Context, nsOpID string, poolLocator s
 			RequestID:   nsOpID,
 			Signer:      burn.Key,
 			Data:        string(data),
+			Config:      burn.Config,
 		}).
 		SetError(&errRes).
 		Post("/api/v1/burn")
@@ -716,6 +723,7 @@ func (ft *FFTokens) TransferTokens(ctx context.Context, nsOpID string, poolLocat
 			RequestID:   nsOpID,
 			Signer:      transfer.Key,
 			Data:        string(data),
+			Config:      transfer.Config,
 		}).
 		SetError(&errRes).
 		Post("/api/v1/transfer")
diff --git a/pkg/core/tokentransfer.go b/pkg/core/tokentransfer.go
index 0fefc90ee..0c3840dfc 100644
--- a/pkg/core/tokentransfer.go
+++ b/pkg/core/tokentransfer.go
@@ -27,23 +27,24 @@ var (
 )
 
 type TokenTransfer struct {
-	Type            TokenTransferType `ffstruct:"TokenTransfer" json:"type" ffenum:"tokentransfertype" ffexcludeinput:"true"`
-	LocalID         *fftypes.UUID     `ffstruct:"TokenTransfer" json:"localId,omitempty" ffexcludeinput:"true"`
-	Pool            *fftypes.UUID     `ffstruct:"TokenTransfer" json:"pool,omitempty"`
-	TokenIndex      string            `ffstruct:"TokenTransfer" json:"tokenIndex,omitempty"`
-	URI             string            `ffstruct:"TokenTransfer" json:"uri,omitempty" ffexcludeinput:"true"`
-	Connector       string            `ffstruct:"TokenTransfer" json:"connector,omitempty" ffexcludeinput:"true"`
-	Namespace       string            `ffstruct:"TokenTransfer" json:"namespace,omitempty" ffexcludeinput:"true"`
-	Key             string            `ffstruct:"TokenTransfer" json:"key,omitempty"`
-	From            string            `ffstruct:"TokenTransfer" json:"from,omitempty" ffexcludeinput:"postTokenMint"`
-	To              string            `ffstruct:"TokenTransfer" json:"to,omitempty" ffexcludeinput:"postTokenBurn"`
-	Amount          fftypes.FFBigInt  `ffstruct:"TokenTransfer" json:"amount"`
-	ProtocolID      string            `ffstruct:"TokenTransfer" json:"protocolId,omitempty" ffexcludeinput:"true"`
-	Message         *fftypes.UUID     `ffstruct:"TokenTransfer" json:"message,omitempty"`
-	MessageHash     *fftypes.Bytes32  `ffstruct:"TokenTransfer" json:"messageHash,omitempty" ffexcludeinput:"true"`
-	Created         *fftypes.FFTime   `ffstruct:"TokenTransfer" json:"created,omitempty" ffexcludeinput:"true"`
-	TX              TransactionRef    `ffstruct:"TokenTransfer" json:"tx" ffexcludeinput:"true"`
-	BlockchainEvent *fftypes.UUID     `ffstruct:"TokenTransfer" json:"blockchainEvent,omitempty" ffexcludeinput:"true"`
+	Type            TokenTransferType  `ffstruct:"TokenTransfer" json:"type" ffenum:"tokentransfertype" ffexcludeinput:"true"`
+	LocalID         *fftypes.UUID      `ffstruct:"TokenTransfer" json:"localId,omitempty" ffexcludeinput:"true"`
+	Pool            *fftypes.UUID      `ffstruct:"TokenTransfer" json:"pool,omitempty"`
+	TokenIndex      string             `ffstruct:"TokenTransfer" json:"tokenIndex,omitempty"`
+	URI             string             `ffstruct:"TokenTransfer" json:"uri,omitempty"`
+	Connector       string             `ffstruct:"TokenTransfer" json:"connector,omitempty" ffexcludeinput:"true"`
+	Namespace       string             `ffstruct:"TokenTransfer" json:"namespace,omitempty" ffexcludeinput:"true"`
+	Key             string             `ffstruct:"TokenTransfer" json:"key,omitempty"`
+	From            string             `ffstruct:"TokenTransfer" json:"from,omitempty" ffexcludeinput:"postTokenMint"`
+	To              string             `ffstruct:"TokenTransfer" json:"to,omitempty" ffexcludeinput:"postTokenBurn"`
+	Amount          fftypes.FFBigInt   `ffstruct:"TokenTransfer" json:"amount"`
+	ProtocolID      string             `ffstruct:"TokenTransfer" json:"protocolId,omitempty" ffexcludeinput:"true"`
+	Message         *fftypes.UUID      `ffstruct:"TokenTransfer" json:"message,omitempty"`
+	MessageHash     *fftypes.Bytes32   `ffstruct:"TokenTransfer" json:"messageHash,omitempty" ffexcludeinput:"true"`
+	Created         *fftypes.FFTime    `ffstruct:"TokenTransfer" json:"created,omitempty" ffexcludeinput:"true"`
+	TX              TransactionRef     `ffstruct:"TokenTransfer" json:"tx" ffexcludeinput:"true"`
+	BlockchainEvent *fftypes.UUID      `ffstruct:"TokenTransfer" json:"blockchainEvent,omitempty" ffexcludeinput:"true"`
+	Config          fftypes.JSONObject `ffstruct:"TokenTransfer" json:"config,omitempty" ffexcludeoutput:"true"` // for REST calls only (not stored)
 }
 
 type TokenTransferInput struct {


Test patch:
diff --git a/internal/tokens/fftokens/fftokens_test.go b/internal/tokens/fftokens/fftokens_test.go
index 4081672df..583f6f8fb 100644
--- a/internal/tokens/fftokens/fftokens_test.go
+++ b/internal/tokens/fftokens/fftokens_test.go
@@ -535,6 +535,10 @@ func TestMintTokens(t *testing.T) {
 			ID:   fftypes.NewUUID(),
 			Type: core.TransactionTypeTokenTransfer,
 		},
+		URI: "FLAPFLIP",
+		Config: fftypes.JSONObject{
+			"foo": "bar",
+		},
 	}
 	opID := fftypes.NewUUID()
 	nsOpID := "ns1:" + opID.String()
@@ -549,11 +553,15 @@ func TestMintTokens(t *testing.T) {
 				"to":          "user1",
 				"amount":      "10",
 				"signer":      "0x123",
-				"requestId":   "ns1:" + opID.String(),
+				"config": map[string]interface{}{
+					"foo": "bar",
+				},
+				"requestId": "ns1:" + opID.String(),
 				"data": fftypes.JSONObject{
 					"tx":     mint.TX.ID.String(),
 					"txtype": core.TransactionTypeTokenTransfer.String(),
 				}.String(),
+				"uri": "FLAPFLIP",
 			}, body)
 
 			res := &http.Response{
@@ -666,6 +674,9 @@ func TestBurnTokens(t *testing.T) {
 			ID:   fftypes.NewUUID(),
 			Type: core.TransactionTypeTokenTransfer,
 		},
+		Config: fftypes.JSONObject{
+			"foo": "bar",
+		},
 	}
 	opID := fftypes.NewUUID()
 	nsOpID := "ns1:" + opID.String()
@@ -681,7 +692,10 @@ func TestBurnTokens(t *testing.T) {
 				"from":        "user1",
 				"amount":      "10",
 				"signer":      "0x123",
-				"requestId":   "ns1:" + opID.String(),
+				"config": map[string]interface{}{
+					"foo": "bar",
+				},
+				"requestId": "ns1:" + opID.String(),
 				"data": fftypes.JSONObject{
 					"tx":     burn.TX.ID.String(),
 					"txtype": core.TransactionTypeTokenTransfer.String(),
@@ -731,6 +745,9 @@ func TestTransferTokens(t *testing.T) {
 			ID:   fftypes.NewUUID(),
 			Type: core.TransactionTypeTokenTransfer,
 		},
+		Config: fftypes.JSONObject{
+			"foo": "bar",
+		},
 	}
 	opID := fftypes.NewUUID()
 	nsOpID := "ns1:" + opID.String()
@@ -747,7 +764,10 @@ func TestTransferTokens(t *testing.T) {
 				"to":          "user2",
 				"amount":      "10",
 				"signer":      "0x123",
-				"requestId":   "ns1:" + opID.String(),
+				"config": map[string]interface{}{
+					"foo": "bar",
+				},
+				"requestId": "ns1:" + opID.String(),
 				"data": fftypes.JSONObject{
 					"tx":     transfer.TX.ID.String(),
 					"txtype": core.TransactionTypeTokenTransfer.String(),