diff --git a/db/migrations/postgres/000033_add_token_connector_fields.down.sql b/db/migrations/postgres/000033_add_token_connector_fields.down.sql new file mode 100644 index 0000000000..5401621393 --- /dev/null +++ b/db/migrations/postgres/000033_add_token_connector_fields.down.sql @@ -0,0 +1,4 @@ +BEGIN; +ALTER TABLE tokenaccount DROP COLUMN connector; +ALTER TABLE tokentransfer DROP COLUMN connector; +COMMIT; diff --git a/db/migrations/postgres/000033_add_token_connector_fields.up.sql b/db/migrations/postgres/000033_add_token_connector_fields.up.sql new file mode 100644 index 0000000000..cb2854fc70 --- /dev/null +++ b/db/migrations/postgres/000033_add_token_connector_fields.up.sql @@ -0,0 +1,17 @@ +BEGIN; + +ALTER TABLE tokenaccount ADD COLUMN connector VARCHAR(64); +ALTER TABLE tokentransfer ADD COLUMN connector VARCHAR(64); + +UPDATE tokenaccount SET connector = pool.connector + FROM (SELECT protocol_id, connector FROM tokenpool) AS pool + WHERE tokenaccount.pool_protocol_id = pool.protocol_id; + +UPDATE tokentransfer SET connector = pool.connector + FROM (SELECT protocol_id, connector FROM tokenpool) AS pool + WHERE tokentransfer.pool_protocol_id = pool.protocol_id; + +ALTER TABLE tokenaccount ALTER COLUMN connector SET NOT NULL; +ALTER TABLE tokentransfer ALTER COLUMN connector SET NOT NULL; + +COMMIT; diff --git a/db/migrations/postgres/000034_rename_tokenaccount_key.down.sql b/db/migrations/postgres/000034_rename_tokenaccount_key.down.sql new file mode 100644 index 0000000000..f07cf93c7a --- /dev/null +++ b/db/migrations/postgres/000034_rename_tokenaccount_key.down.sql @@ -0,0 +1,3 @@ +BEGIN; +ALTER TABLE tokenaccount RENAME COLUMN key TO identity; +COMMIT; diff --git a/db/migrations/postgres/000034_rename_tokenaccount_key.up.sql b/db/migrations/postgres/000034_rename_tokenaccount_key.up.sql new file mode 100644 index 0000000000..073b61194a --- /dev/null +++ b/db/migrations/postgres/000034_rename_tokenaccount_key.up.sql @@ -0,0 +1,3 @@ +BEGIN; +ALTER TABLE tokenaccount RENAME COLUMN identity TO key; +COMMIT; diff --git a/db/migrations/postgres/000035_add_tokenaccount_updated.down.sql b/db/migrations/postgres/000035_add_tokenaccount_updated.down.sql new file mode 100644 index 0000000000..2dd70c89db --- /dev/null +++ b/db/migrations/postgres/000035_add_tokenaccount_updated.down.sql @@ -0,0 +1,3 @@ +BEGIN; +ALTER TABLE tokenaccount DROP COLUMN updated; +COMMIT; diff --git a/db/migrations/postgres/000035_add_tokenaccount_updated.up.sql b/db/migrations/postgres/000035_add_tokenaccount_updated.up.sql new file mode 100644 index 0000000000..b73902bfaa --- /dev/null +++ b/db/migrations/postgres/000035_add_tokenaccount_updated.up.sql @@ -0,0 +1,5 @@ +BEGIN; +ALTER TABLE tokenaccount ADD COLUMN updated BIGINT; +UPDATE tokenaccount SET updated = 0; +ALTER TABLE tokenaccount ALTER COLUMN updated SET NOT NULL; +COMMIT; diff --git a/db/migrations/postgres/000036_add_tokenpool_standard.down.sql b/db/migrations/postgres/000036_add_tokenpool_standard.down.sql new file mode 100644 index 0000000000..790ccb46d5 --- /dev/null +++ b/db/migrations/postgres/000036_add_tokenpool_standard.down.sql @@ -0,0 +1,3 @@ +BEGIN; +ALTER TABLE tokenpool DROP COLUMN standard; +COMMIT; diff --git a/db/migrations/postgres/000036_add_tokenpool_standard.up.sql b/db/migrations/postgres/000036_add_tokenpool_standard.up.sql new file mode 100644 index 0000000000..ed231a68e8 --- /dev/null +++ b/db/migrations/postgres/000036_add_tokenpool_standard.up.sql @@ -0,0 +1,3 @@ +BEGIN; +ALTER TABLE tokenpool ADD COLUMN standard VARCHAR(64); +COMMIT; diff --git a/db/migrations/sqlite/000033_add_token_connector_fields.down.sql b/db/migrations/sqlite/000033_add_token_connector_fields.down.sql new file mode 100644 index 0000000000..ec7b622f31 --- /dev/null +++ b/db/migrations/sqlite/000033_add_token_connector_fields.down.sql @@ -0,0 +1,2 @@ +ALTER TABLE tokenaccount DROP COLUMN connector; +ALTER TABLE tokentransfer DROP COLUMN connector; diff --git a/db/migrations/sqlite/000033_add_token_connector_fields.up.sql b/db/migrations/sqlite/000033_add_token_connector_fields.up.sql new file mode 100644 index 0000000000..c2b5349af0 --- /dev/null +++ b/db/migrations/sqlite/000033_add_token_connector_fields.up.sql @@ -0,0 +1,11 @@ +DELETE FROM tokenaccount; +ALTER TABLE tokenaccount ADD COLUMN connector VARCHAR(64); +ALTER TABLE tokentransfer ADD COLUMN connector VARCHAR(64); + +UPDATE tokenaccount SET connector = pool.connector + FROM (SELECT protocol_id, connector FROM tokenpool) AS pool + WHERE tokenaccount.pool_protocol_id = pool.protocol_id; + +UPDATE tokentransfer SET connector = pool.connector + FROM (SELECT protocol_id, connector FROM tokenpool) AS pool + WHERE tokentransfer.pool_protocol_id = pool.protocol_id; diff --git a/db/migrations/sqlite/000034_rename_tokenaccount_key.down.sql b/db/migrations/sqlite/000034_rename_tokenaccount_key.down.sql new file mode 100644 index 0000000000..86a43ac556 --- /dev/null +++ b/db/migrations/sqlite/000034_rename_tokenaccount_key.down.sql @@ -0,0 +1 @@ +ALTER TABLE tokenaccount RENAME COLUMN key TO identity; diff --git a/db/migrations/sqlite/000034_rename_tokenaccount_key.up.sql b/db/migrations/sqlite/000034_rename_tokenaccount_key.up.sql new file mode 100644 index 0000000000..9e6365e04c --- /dev/null +++ b/db/migrations/sqlite/000034_rename_tokenaccount_key.up.sql @@ -0,0 +1 @@ +ALTER TABLE tokenaccount RENAME COLUMN identity TO key; diff --git a/db/migrations/sqlite/000035_add_tokenaccount_updated.down.sql b/db/migrations/sqlite/000035_add_tokenaccount_updated.down.sql new file mode 100644 index 0000000000..b32c3b18ad --- /dev/null +++ b/db/migrations/sqlite/000035_add_tokenaccount_updated.down.sql @@ -0,0 +1 @@ +ALTER TABLE tokenaccount DROP COLUMN updated; diff --git a/db/migrations/sqlite/000035_add_tokenaccount_updated.up.sql b/db/migrations/sqlite/000035_add_tokenaccount_updated.up.sql new file mode 100644 index 0000000000..8a609736f3 --- /dev/null +++ b/db/migrations/sqlite/000035_add_tokenaccount_updated.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE tokenaccount ADD COLUMN updated BIGINT; +UPDATE tokenaccount SET updated = 0; diff --git a/db/migrations/sqlite/000036_add_tokenpool_standard.down.sql b/db/migrations/sqlite/000036_add_tokenpool_standard.down.sql new file mode 100644 index 0000000000..e268a49ee1 --- /dev/null +++ b/db/migrations/sqlite/000036_add_tokenpool_standard.down.sql @@ -0,0 +1 @@ +ALTER TABLE tokenpool DROP COLUMN standard; diff --git a/db/migrations/sqlite/000036_add_tokenpool_standard.up.sql b/db/migrations/sqlite/000036_add_tokenpool_standard.up.sql new file mode 100644 index 0000000000..b0226f5e17 --- /dev/null +++ b/db/migrations/sqlite/000036_add_tokenpool_standard.up.sql @@ -0,0 +1 @@ +ALTER TABLE tokenpool ADD COLUMN standard VARCHAR(64); diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index 8b44d824ff..760a09548f 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -4330,6 +4330,11 @@ paths: name: protocolid schema: type: string + - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' + in: query + name: standard + schema: + type: string - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' in: query name: symbol @@ -4397,6 +4402,8 @@ paths: type: string protocolId: type: string + standard: + type: string symbol: type: string tx: @@ -4483,6 +4490,8 @@ paths: type: string protocolId: type: string + standard: + type: string symbol: type: string tx: @@ -4516,6 +4525,8 @@ paths: type: string protocolId: type: string + standard: + type: string symbol: type: string tx: @@ -4583,6 +4594,8 @@ paths: type: string protocolId: type: string + standard: + type: string symbol: type: string tx: @@ -4635,7 +4648,12 @@ paths: type: string - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' in: query - name: identity + name: connector + schema: + type: string + - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' + in: query + name: key schema: type: string - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' @@ -4648,6 +4666,11 @@ paths: name: tokenindex schema: type: string + - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' + in: query + name: updated + schema: + type: string - description: Sort field. For multi-field sort use comma separated values (or multiple query values) with '-' prefix for descending in: query @@ -4690,12 +4713,15 @@ paths: items: properties: balance: {} - identity: + connector: + type: string + key: type: string poolProtocolId: type: string tokenIndex: type: string + updated: {} type: object type: array description: Success @@ -4743,6 +4769,8 @@ paths: schema: properties: amount: {} + connector: + type: string created: {} from: type: string @@ -4865,6 +4893,8 @@ paths: schema: properties: amount: {} + connector: + type: string created: {} from: type: string @@ -4896,6 +4926,8 @@ paths: schema: properties: amount: {} + connector: + type: string created: {} from: type: string @@ -4965,6 +4997,8 @@ paths: schema: properties: amount: {} + connector: + type: string created: {} from: type: string @@ -5087,6 +5121,8 @@ paths: schema: properties: amount: {} + connector: + type: string created: {} from: type: string @@ -5118,6 +5154,8 @@ paths: schema: properties: amount: {} + connector: + type: string created: {} from: type: string @@ -5181,6 +5219,11 @@ paths: name: amount schema: type: string + - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' + in: query + name: connector + schema: + type: string - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' in: query name: created @@ -5268,6 +5311,8 @@ paths: items: properties: amount: {} + connector: + type: string created: {} from: type: string @@ -5337,6 +5382,8 @@ paths: schema: properties: amount: {} + connector: + type: string created: {} from: type: string @@ -5459,6 +5506,8 @@ paths: schema: properties: amount: {} + connector: + type: string created: {} from: type: string @@ -5490,6 +5539,8 @@ paths: schema: properties: amount: {} + connector: + type: string created: {} from: type: string @@ -5543,7 +5594,12 @@ paths: type: string - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' in: query - name: identity + name: connector + schema: + type: string + - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' + in: query + name: key schema: type: string - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' @@ -5556,6 +5612,11 @@ paths: name: tokenindex schema: type: string + - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' + in: query + name: updated + schema: + type: string - description: Sort field. For multi-field sort use comma separated values (or multiple query values) with '-' prefix for descending in: query @@ -5598,12 +5659,15 @@ paths: items: properties: balance: {} - identity: + connector: + type: string + key: type: string poolProtocolId: type: string tokenIndex: type: string + updated: {} type: object type: array description: Success @@ -5696,6 +5760,11 @@ paths: name: protocolid schema: type: string + - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' + in: query + name: standard + schema: + type: string - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' in: query name: symbol @@ -5763,6 +5832,8 @@ paths: type: string protocolId: type: string + standard: + type: string symbol: type: string tx: @@ -5802,6 +5873,11 @@ paths: name: amount schema: type: string + - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' + in: query + name: connector + schema: + type: string - description: 'Data filter field. Prefixes supported: > >= < <= @ ^ ! !@ !^' in: query name: created @@ -5889,6 +5965,8 @@ paths: items: properties: amount: {} + connector: + type: string created: {} from: type: string diff --git a/internal/apiserver/route_post_token_burn.go b/internal/apiserver/route_post_token_burn.go index 35e579b55f..232e080f52 100644 --- a/internal/apiserver/route_post_token_burn.go +++ b/internal/apiserver/route_post_token_burn.go @@ -41,7 +41,7 @@ var postTokenBurn = &oapispec.Route{ FilterFactory: nil, Description: i18n.MsgTBD, JSONInputValue: func() interface{} { return &fftypes.TokenTransferInput{} }, - JSONInputMask: []string{"Type", "LocalID", "PoolProtocolID", "To", "ProtocolID", "MessageHash", "TX", "Created"}, + JSONInputMask: []string{"Type", "LocalID", "PoolProtocolID", "To", "ProtocolID", "MessageHash", "Connector", "TX", "Created"}, JSONOutputValue: func() interface{} { return &fftypes.TokenTransfer{} }, JSONOutputCodes: []int{http.StatusAccepted, http.StatusOK}, JSONHandler: func(r *oapispec.APIRequest) (output interface{}, err error) { diff --git a/internal/apiserver/route_post_token_mint.go b/internal/apiserver/route_post_token_mint.go index b134aef51f..608f12d7a9 100644 --- a/internal/apiserver/route_post_token_mint.go +++ b/internal/apiserver/route_post_token_mint.go @@ -41,7 +41,7 @@ var postTokenMint = &oapispec.Route{ FilterFactory: nil, Description: i18n.MsgTBD, JSONInputValue: func() interface{} { return &fftypes.TokenTransferInput{} }, - JSONInputMask: []string{"Type", "LocalID", "PoolProtocolID", "TokenIndex", "From", "ProtocolID", "MessageHash", "TX", "Created"}, + JSONInputMask: []string{"Type", "LocalID", "PoolProtocolID", "TokenIndex", "From", "ProtocolID", "MessageHash", "Connector", "TX", "Created"}, JSONOutputValue: func() interface{} { return &fftypes.TokenTransfer{} }, JSONOutputCodes: []int{http.StatusAccepted, http.StatusOK}, JSONHandler: func(r *oapispec.APIRequest) (output interface{}, err error) { diff --git a/internal/apiserver/route_post_token_pool.go b/internal/apiserver/route_post_token_pool.go index eef994a7f2..e92c87eb65 100644 --- a/internal/apiserver/route_post_token_pool.go +++ b/internal/apiserver/route_post_token_pool.go @@ -40,7 +40,7 @@ var postTokenPool = &oapispec.Route{ FilterFactory: nil, Description: i18n.MsgTBD, JSONInputValue: func() interface{} { return &fftypes.TokenPool{} }, - JSONInputMask: []string{"ID", "Namespace", "ProtocolID", "TX", "Connector", "Message", "Created"}, + JSONInputMask: []string{"ID", "Namespace", "Standard", "ProtocolID", "TX", "Connector", "Message", "Created"}, JSONOutputValue: func() interface{} { return &fftypes.TokenPool{} }, JSONOutputCodes: []int{http.StatusAccepted, http.StatusOK}, JSONHandler: func(r *oapispec.APIRequest) (output interface{}, err error) { diff --git a/internal/apiserver/route_post_token_transfer.go b/internal/apiserver/route_post_token_transfer.go index 970f7ec38f..c36ef24542 100644 --- a/internal/apiserver/route_post_token_transfer.go +++ b/internal/apiserver/route_post_token_transfer.go @@ -41,7 +41,7 @@ var postTokenTransfer = &oapispec.Route{ FilterFactory: nil, Description: i18n.MsgTBD, JSONInputValue: func() interface{} { return &fftypes.TokenTransferInput{} }, - JSONInputMask: []string{"Type", "LocalID", "PoolProtocolID", "ProtocolID", "MessageHash", "TX", "Created"}, + JSONInputMask: []string{"Type", "LocalID", "PoolProtocolID", "ProtocolID", "MessageHash", "Connector", "TX", "Created"}, JSONOutputValue: func() interface{} { return &fftypes.TokenTransfer{} }, JSONOutputCodes: []int{http.StatusAccepted, http.StatusOK}, JSONHandler: func(r *oapispec.APIRequest) (output interface{}, err error) { diff --git a/internal/assets/manager.go b/internal/assets/manager.go index 0c67694cd7..94e86afc97 100644 --- a/internal/assets/manager.go +++ b/internal/assets/manager.go @@ -35,19 +35,19 @@ import ( ) type Manager interface { - CreateTokenPool(ctx context.Context, ns, typeName string, pool *fftypes.TokenPool, waitConfirm bool) (*fftypes.TokenPool, error) + CreateTokenPool(ctx context.Context, ns, connector string, pool *fftypes.TokenPool, waitConfirm bool) (*fftypes.TokenPool, error) GetTokenPools(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.TokenPool, *database.FilterResult, error) - GetTokenPoolsByType(ctx context.Context, ns, typeName string, filter database.AndFilter) ([]*fftypes.TokenPool, *database.FilterResult, error) - GetTokenPool(ctx context.Context, ns, typeName, poolName string) (*fftypes.TokenPool, error) + GetTokenPoolsByType(ctx context.Context, ns, connector string, filter database.AndFilter) ([]*fftypes.TokenPool, *database.FilterResult, error) + GetTokenPool(ctx context.Context, ns, connector, poolName string) (*fftypes.TokenPool, error) ValidateTokenPoolTx(ctx context.Context, pool *fftypes.TokenPool, protocolTxID string) error GetTokenAccounts(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.TokenAccount, *database.FilterResult, error) - GetTokenAccountsByPool(ctx context.Context, ns, typeName, poolName string, filter database.AndFilter) ([]*fftypes.TokenAccount, *database.FilterResult, error) + GetTokenAccountsByPool(ctx context.Context, ns, connector, poolName string, filter database.AndFilter) ([]*fftypes.TokenAccount, *database.FilterResult, error) GetTokenTransfers(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.TokenTransfer, *database.FilterResult, error) - GetTokenTransfersByPool(ctx context.Context, ns, typeName, poolName string, filter database.AndFilter) ([]*fftypes.TokenTransfer, *database.FilterResult, error) - NewTransfer(ns, typeName, poolName string, transfer *fftypes.TokenTransferInput) sysmessaging.MessageSender - MintTokens(ctx context.Context, ns, typeName, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (*fftypes.TokenTransfer, error) - BurnTokens(ctx context.Context, ns, typeName, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (*fftypes.TokenTransfer, error) - TransferTokens(ctx context.Context, ns, typeName, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (*fftypes.TokenTransfer, error) + GetTokenTransfersByPool(ctx context.Context, ns, connector, poolName string, filter database.AndFilter) ([]*fftypes.TokenTransfer, *database.FilterResult, error) + NewTransfer(ns, connector, poolName string, transfer *fftypes.TokenTransferInput) sysmessaging.MessageSender + MintTokens(ctx context.Context, ns, connector, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (*fftypes.TokenTransfer, error) + BurnTokens(ctx context.Context, ns, connector, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (*fftypes.TokenTransfer, error) + TransferTokens(ctx context.Context, ns, connector, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (*fftypes.TokenTransfer, error) GetTokenConnectors(ctx context.Context, ns string) ([]*fftypes.TokenConnector, error) // Bound token callbacks @@ -110,8 +110,8 @@ func (am *assetManager) GetTokenAccounts(ctx context.Context, ns string, filter return am.database.GetTokenAccounts(ctx, filter) } -func (am *assetManager) GetTokenAccountsByPool(ctx context.Context, ns, typeName, poolName string, filter database.AndFilter) ([]*fftypes.TokenAccount, *database.FilterResult, error) { - pool, err := am.GetTokenPool(ctx, ns, typeName, poolName) +func (am *assetManager) GetTokenAccountsByPool(ctx context.Context, ns, connector, poolName string, filter database.AndFilter) ([]*fftypes.TokenAccount, *database.FilterResult, error) { + pool, err := am.GetTokenPool(ctx, ns, connector, poolName) if err != nil { return nil, nil, err } diff --git a/internal/assets/token_pool.go b/internal/assets/token_pool.go index 90d7b6545e..d16eb442a5 100644 --- a/internal/assets/token_pool.go +++ b/internal/assets/token_pool.go @@ -49,11 +49,11 @@ func retrieveTokenPoolCreateInputs(ctx context.Context, op *fftypes.Operation, p return nil } -func (am *assetManager) CreateTokenPool(ctx context.Context, ns string, typeName string, pool *fftypes.TokenPool, waitConfirm bool) (*fftypes.TokenPool, error) { - return am.createTokenPoolWithID(ctx, fftypes.NewUUID(), ns, typeName, pool, waitConfirm) +func (am *assetManager) CreateTokenPool(ctx context.Context, ns string, connector string, pool *fftypes.TokenPool, waitConfirm bool) (*fftypes.TokenPool, error) { + return am.createTokenPoolWithID(ctx, fftypes.NewUUID(), ns, connector, pool, waitConfirm) } -func (am *assetManager) createTokenPoolWithID(ctx context.Context, id *fftypes.UUID, ns string, typeName string, pool *fftypes.TokenPool, waitConfirm bool) (*fftypes.TokenPool, error) { +func (am *assetManager) createTokenPoolWithID(ctx context.Context, id *fftypes.UUID, ns string, connector string, pool *fftypes.TokenPool, waitConfirm bool) (*fftypes.TokenPool, error) { if err := am.data.VerifyNamespaceExists(ctx, ns); err != nil { return nil, err } @@ -66,15 +66,19 @@ func (am *assetManager) createTokenPoolWithID(ctx context.Context, id *fftypes.U pool.Key = org.Identity } - plugin, err := am.selectTokenPlugin(ctx, typeName) + plugin, err := am.selectTokenPlugin(ctx, connector) if err != nil { return nil, err } + pool.ID = id + pool.Namespace = ns + pool.Connector = connector + if waitConfirm { requestID := fftypes.NewUUID() return am.syncasync.SendConfirmTokenPool(ctx, ns, requestID, func(ctx context.Context) error { - _, err := am.createTokenPoolWithID(ctx, requestID, ns, typeName, pool, false) + _, err := am.createTokenPoolWithID(ctx, requestID, ns, connector, pool, false) return err }) } @@ -96,8 +100,6 @@ func (am *assetManager) createTokenPoolWithID(ctx context.Context, id *fftypes.U return nil, err } - pool.ID = id - pool.Namespace = ns pool.TX.ID = tx.ID pool.TX.Type = tx.Subject.Type @@ -125,8 +127,8 @@ func (am *assetManager) GetTokenPools(ctx context.Context, ns string, filter dat return am.database.GetTokenPools(ctx, am.scopeNS(ns, filter)) } -func (am *assetManager) GetTokenPoolsByType(ctx context.Context, ns string, typeName string, filter database.AndFilter) ([]*fftypes.TokenPool, *database.FilterResult, error) { - if _, err := am.selectTokenPlugin(ctx, typeName); err != nil { +func (am *assetManager) GetTokenPoolsByType(ctx context.Context, ns string, connector string, filter database.AndFilter) ([]*fftypes.TokenPool, *database.FilterResult, error) { + if _, err := am.selectTokenPlugin(ctx, connector); err != nil { return nil, nil, err } if err := fftypes.ValidateFFNameField(ctx, ns, "namespace"); err != nil { @@ -135,8 +137,8 @@ func (am *assetManager) GetTokenPoolsByType(ctx context.Context, ns string, type return am.database.GetTokenPools(ctx, am.scopeNS(ns, filter)) } -func (am *assetManager) GetTokenPool(ctx context.Context, ns, typeName, poolName string) (*fftypes.TokenPool, error) { - if _, err := am.selectTokenPlugin(ctx, typeName); err != nil { +func (am *assetManager) GetTokenPool(ctx context.Context, ns, connector, poolName string) (*fftypes.TokenPool, error) { + if _, err := am.selectTokenPlugin(ctx, connector); err != nil { return nil, err } if err := fftypes.ValidateFFNameField(ctx, ns, "namespace"); err != nil { diff --git a/internal/assets/token_transfer.go b/internal/assets/token_transfer.go index 5e7e0d86bc..51758a70e5 100644 --- a/internal/assets/token_transfer.go +++ b/internal/assets/token_transfer.go @@ -37,19 +37,19 @@ func (am *assetManager) GetTokenTransfers(ctx context.Context, ns string, filter return am.database.GetTokenTransfers(ctx, filter) } -func (am *assetManager) GetTokenTransfersByPool(ctx context.Context, ns, typeName, name string, filter database.AndFilter) ([]*fftypes.TokenTransfer, *database.FilterResult, error) { - pool, err := am.GetTokenPool(ctx, ns, typeName, name) +func (am *assetManager) GetTokenTransfersByPool(ctx context.Context, ns, connector, name string, filter database.AndFilter) ([]*fftypes.TokenTransfer, *database.FilterResult, error) { + pool, err := am.GetTokenPool(ctx, ns, connector, name) if err != nil { return nil, nil, err } return am.database.GetTokenTransfers(ctx, filter.Condition(filter.Builder().Eq("poolprotocolid", pool.ProtocolID))) } -func (am *assetManager) NewTransfer(ns, typeName, poolName string, transfer *fftypes.TokenTransferInput) sysmessaging.MessageSender { +func (am *assetManager) NewTransfer(ns, connector, poolName string, transfer *fftypes.TokenTransferInput) sysmessaging.MessageSender { sender := &transferSender{ mgr: am, namespace: ns, - typeName: typeName, + connector: connector, poolName: poolName, transfer: transfer, } @@ -60,7 +60,7 @@ func (am *assetManager) NewTransfer(ns, typeName, poolName string, transfer *fft type transferSender struct { mgr *assetManager namespace string - typeName string + connector string poolName string transfer *fftypes.TokenTransferInput sendCallback sysmessaging.BeforeSendCallback @@ -81,9 +81,10 @@ func (s *transferSender) BeforeSend(cb sysmessaging.BeforeSendCallback) sysmessa func (s *transferSender) setDefaults() { s.transfer.LocalID = fftypes.NewUUID() + s.transfer.Connector = s.connector } -func (am *assetManager) MintTokens(ctx context.Context, ns, typeName, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (out *fftypes.TokenTransfer, err error) { +func (am *assetManager) MintTokens(ctx context.Context, ns, connector, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (out *fftypes.TokenTransfer, err error) { transfer.Type = fftypes.TokenTransferTypeMint if transfer.Key == "" { org, err := am.identity.GetLocalOrganization(ctx) @@ -97,7 +98,7 @@ func (am *assetManager) MintTokens(ctx context.Context, ns, typeName, poolName s transfer.To = transfer.Key } - sender := am.NewTransfer(ns, typeName, poolName, transfer) + sender := am.NewTransfer(ns, connector, poolName, transfer) if waitConfirm { err = sender.SendAndWait(ctx) } else { @@ -106,7 +107,7 @@ func (am *assetManager) MintTokens(ctx context.Context, ns, typeName, poolName s return &transfer.TokenTransfer, err } -func (am *assetManager) BurnTokens(ctx context.Context, ns, typeName, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (out *fftypes.TokenTransfer, err error) { +func (am *assetManager) BurnTokens(ctx context.Context, ns, connector, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (out *fftypes.TokenTransfer, err error) { transfer.Type = fftypes.TokenTransferTypeBurn if transfer.Key == "" { org, err := am.identity.GetLocalOrganization(ctx) @@ -120,7 +121,7 @@ func (am *assetManager) BurnTokens(ctx context.Context, ns, typeName, poolName s } transfer.To = "" - sender := am.NewTransfer(ns, typeName, poolName, transfer) + sender := am.NewTransfer(ns, connector, poolName, transfer) if waitConfirm { err = sender.SendAndWait(ctx) } else { @@ -129,7 +130,7 @@ func (am *assetManager) BurnTokens(ctx context.Context, ns, typeName, poolName s return &transfer.TokenTransfer, err } -func (am *assetManager) TransferTokens(ctx context.Context, ns, typeName, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (out *fftypes.TokenTransfer, err error) { +func (am *assetManager) TransferTokens(ctx context.Context, ns, connector, poolName string, transfer *fftypes.TokenTransferInput, waitConfirm bool) (out *fftypes.TokenTransfer, err error) { transfer.Type = fftypes.TokenTransferTypeTransfer if transfer.Key == "" { org, err := am.identity.GetLocalOrganization(ctx) @@ -148,7 +149,7 @@ func (am *assetManager) TransferTokens(ctx context.Context, ns, typeName, poolNa return nil, i18n.NewError(ctx, i18n.MsgCannotTransferToSelf) } - sender := am.NewTransfer(ns, typeName, poolName, transfer) + sender := am.NewTransfer(ns, connector, poolName, transfer) if waitConfirm { err = sender.SendAndWait(ctx) } else { @@ -158,11 +159,11 @@ func (am *assetManager) TransferTokens(ctx context.Context, ns, typeName, poolNa } func (s *transferSender) resolveAndSend(ctx context.Context, waitConfirm bool) (err error) { - plugin, err := s.mgr.selectTokenPlugin(ctx, s.typeName) + plugin, err := s.mgr.selectTokenPlugin(ctx, s.connector) if err != nil { return err } - pool, err := s.mgr.GetTokenPool(ctx, s.namespace, s.typeName, s.poolName) + pool, err := s.mgr.GetTokenPool(ctx, s.namespace, s.connector, s.poolName) if err != nil { return err } diff --git a/internal/assets/token_transfer_test.go b/internal/assets/token_transfer_test.go index 3018cce8d6..543481bc52 100644 --- a/internal/assets/token_transfer_test.go +++ b/internal/assets/token_transfer_test.go @@ -395,7 +395,7 @@ func TestTransferTokensInvalidType(t *testing.T) { sender := &transferSender{ mgr: am, namespace: "ns1", - typeName: "magic-tokens", + connector: "magic-tokens", poolName: "pool1", transfer: transfer, } diff --git a/internal/database/sqlcommon/tokenaccount_sql.go b/internal/database/sqlcommon/tokenaccount_sql.go index bda07ab062..796288a35d 100644 --- a/internal/database/sqlcommon/tokenaccount_sql.go +++ b/internal/database/sqlcommon/tokenaccount_sql.go @@ -31,8 +31,10 @@ var ( tokenAccountColumns = []string{ "pool_protocol_id", "token_index", - "identity", + "connector", + "key", "balance", + "updated", } tokenAccountFilterFieldMap = map[string]string{ "poolprotocolid": "pool_protocol_id", @@ -53,7 +55,7 @@ func (s *SQLCommon) AddTokenAccountBalance(ctx context.Context, account *fftypes Where(sq.And{ sq.Eq{"pool_protocol_id": account.PoolProtocolID}, sq.Eq{"token_index": account.TokenIndex}, - sq.Eq{"identity": account.Identity}, + sq.Eq{"key": account.Key}, }), ) if err != nil { @@ -74,10 +76,11 @@ func (s *SQLCommon) AddTokenAccountBalance(ctx context.Context, account *fftypes if err = s.updateTx(ctx, tx, sq.Update("tokenaccount"). Set("balance", balance). + Set("updated", fftypes.Now()). Where(sq.And{ sq.Eq{"pool_protocol_id": account.PoolProtocolID}, sq.Eq{"token_index": account.TokenIndex}, - sq.Eq{"identity": account.Identity}, + sq.Eq{"key": account.Key}, }), nil, ); err != nil { @@ -90,8 +93,10 @@ func (s *SQLCommon) AddTokenAccountBalance(ctx context.Context, account *fftypes Values( account.PoolProtocolID, account.TokenIndex, - account.Identity, + account.Connector, + account.Key, account.Amount, + fftypes.Now(), ), nil, ); err != nil { @@ -107,8 +112,10 @@ func (s *SQLCommon) tokenAccountResult(ctx context.Context, row *sql.Rows) (*fft err := row.Scan( &account.PoolProtocolID, &account.TokenIndex, - &account.Identity, + &account.Connector, + &account.Key, &account.Balance, + &account.Updated, ) if err != nil { return nil, i18n.WrapError(ctx, err, i18n.MsgDBReadErr, "tokenaccount") @@ -140,12 +147,12 @@ func (s *SQLCommon) getTokenAccountPred(ctx context.Context, desc string, pred i return account, nil } -func (s *SQLCommon) GetTokenAccount(ctx context.Context, protocolID, tokenIndex, identity string) (message *fftypes.TokenAccount, err error) { - desc := fftypes.TokenAccountIdentifier(protocolID, tokenIndex, identity) +func (s *SQLCommon) GetTokenAccount(ctx context.Context, protocolID, tokenIndex, key string) (message *fftypes.TokenAccount, err error) { + desc := fftypes.TokenAccountIdentifier(protocolID, tokenIndex, key) return s.getTokenAccountPred(ctx, desc, sq.And{ sq.Eq{"pool_protocol_id": protocolID}, sq.Eq{"token_index": tokenIndex}, - sq.Eq{"identity": identity}, + sq.Eq{"key": key}, }) } diff --git a/internal/database/sqlcommon/tokenaccount_sql_test.go b/internal/database/sqlcommon/tokenaccount_sql_test.go index 1a80df0d2a..6909e0b34b 100644 --- a/internal/database/sqlcommon/tokenaccount_sql_test.go +++ b/internal/database/sqlcommon/tokenaccount_sql_test.go @@ -39,13 +39,15 @@ func TestTokenAccountE2EWithDB(t *testing.T) { operation := &fftypes.TokenBalanceChange{ PoolProtocolID: "F1", TokenIndex: "1", - Identity: "0x0", + Connector: "erc1155", + Key: "0x0", } operation.Amount.Int().SetInt64(10) account := &fftypes.TokenAccount{ PoolProtocolID: "F1", TokenIndex: "1", - Identity: "0x0", + Connector: "erc1155", + Key: "0x0", } account.Balance.Int().SetInt64(10) accountJson, _ := json.Marshal(&account) @@ -57,6 +59,8 @@ func TestTokenAccountE2EWithDB(t *testing.T) { accountRead, err := s.GetTokenAccount(ctx, "F1", "1", "0x0") assert.NoError(t, err) assert.NotNil(t, accountRead) + assert.Greater(t, accountRead.Updated.UnixNano(), int64(0)) + accountRead.Updated = nil accountReadJson, _ := json.Marshal(&accountRead) assert.Equal(t, string(accountJson), string(accountReadJson)) @@ -65,12 +69,14 @@ func TestTokenAccountE2EWithDB(t *testing.T) { filter := fb.And( fb.Eq("poolprotocolid", account.PoolProtocolID), fb.Eq("tokenindex", account.TokenIndex), - fb.Eq("identity", account.Identity), + fb.Eq("key", account.Key), ) accounts, res, err := s.GetTokenAccounts(ctx, filter.Count(true)) assert.NoError(t, err) assert.Equal(t, 1, len(accounts)) assert.Equal(t, int64(1), *res.TotalCount) + assert.Greater(t, accounts[0].Updated.UnixNano(), int64(0)) + accounts[0].Updated = nil accountReadJson, _ = json.Marshal(accounts[0]) assert.Equal(t, string(accountJson), string(accountReadJson)) @@ -82,6 +88,8 @@ func TestTokenAccountE2EWithDB(t *testing.T) { accountRead, err = s.GetTokenAccount(ctx, "F1", "1", "0x0") assert.NoError(t, err) assert.NotNil(t, accountRead) + assert.Greater(t, accountRead.Updated.UnixNano(), int64(0)) + accountRead.Updated = nil accountReadJson, _ = json.Marshal(&accountRead) account.Balance.Int().SetInt64(20) accountJson, _ = json.Marshal(&account) @@ -158,14 +166,15 @@ func TestAddTokenAccountBalanceInsertSuccess(t *testing.T) { operation := &fftypes.TokenBalanceChange{ PoolProtocolID: "F1", TokenIndex: "1", - Identity: "0x0", + Connector: "erc1155", + Key: "0x0", } operation.Amount.Int().SetInt64(10) db.ExpectBegin() db.ExpectQuery("SELECT .*").WillReturnRows(sqlmock.NewRows([]string{"id"})) db.ExpectExec("INSERT .*"). - WithArgs("F1", "1", "0x0", sqlmock.AnyArg()). + WithArgs("F1", "1", "erc1155", "0x0", sqlmock.AnyArg(), sqlmock.AnyArg()). WillReturnResult(sqlmock.NewResult(1, 1)) db.ExpectCommit() err := s.AddTokenAccountBalance(context.Background(), operation) @@ -180,7 +189,7 @@ func TestAddTokenAccountBalanceUpdateSuccess(t *testing.T) { operation := &fftypes.TokenBalanceChange{ PoolProtocolID: "F1", TokenIndex: "1", - Identity: "0x0", + Key: "0x0", } operation.Amount.Int().SetInt64(10) diff --git a/internal/database/sqlcommon/tokenpool_sql.go b/internal/database/sqlcommon/tokenpool_sql.go index ff1da36aaf..f2a0a25c92 100644 --- a/internal/database/sqlcommon/tokenpool_sql.go +++ b/internal/database/sqlcommon/tokenpool_sql.go @@ -32,6 +32,7 @@ var ( "id", "namespace", "name", + "standard", "protocol_id", "type", "connector", @@ -83,6 +84,7 @@ func (s *SQLCommon) UpsertTokenPool(ctx context.Context, pool *fftypes.TokenPool sq.Update("tokenpool"). Set("namespace", pool.Namespace). Set("name", pool.Name). + Set("standard", pool.Standard). Set("protocol_id", pool.ProtocolID). Set("type", pool.Type). Set("connector", pool.Connector). @@ -107,6 +109,7 @@ func (s *SQLCommon) UpsertTokenPool(ctx context.Context, pool *fftypes.TokenPool pool.ID, pool.Namespace, pool.Name, + pool.Standard, pool.ProtocolID, pool.Type, pool.Connector, @@ -134,6 +137,7 @@ func (s *SQLCommon) tokenPoolResult(ctx context.Context, row *sql.Rows) (*fftype &pool.ID, &pool.Namespace, &pool.Name, + &pool.Standard, &pool.ProtocolID, &pool.Type, &pool.Connector, diff --git a/internal/database/sqlcommon/tokenpool_sql_test.go b/internal/database/sqlcommon/tokenpool_sql_test.go index 61040847db..82c41e5d8b 100644 --- a/internal/database/sqlcommon/tokenpool_sql_test.go +++ b/internal/database/sqlcommon/tokenpool_sql_test.go @@ -41,6 +41,7 @@ func TestTokenPoolE2EWithDB(t *testing.T) { ID: poolID, Namespace: "ns1", Name: "my-pool", + Standard: "ERC1155", Type: fftypes.TokenTypeFungible, ProtocolID: "12345", Connector: "erc1155", diff --git a/internal/database/sqlcommon/tokentransfer_sql.go b/internal/database/sqlcommon/tokentransfer_sql.go index de163d06f2..ffc1e5bf35 100644 --- a/internal/database/sqlcommon/tokentransfer_sql.go +++ b/internal/database/sqlcommon/tokentransfer_sql.go @@ -33,6 +33,7 @@ var ( "local_id", "pool_protocol_id", "token_index", + "connector", "key", "from_key", "to_key", @@ -81,6 +82,7 @@ func (s *SQLCommon) UpsertTokenTransfer(ctx context.Context, transfer *fftypes.T Set("local_id", transfer.LocalID). Set("pool_protocol_id", transfer.PoolProtocolID). Set("token_index", transfer.TokenIndex). + Set("connector", transfer.Connector). Set("key", transfer.Key). Set("from_key", transfer.From). Set("to_key", transfer.To). @@ -105,6 +107,7 @@ func (s *SQLCommon) UpsertTokenTransfer(ctx context.Context, transfer *fftypes.T transfer.LocalID, transfer.PoolProtocolID, transfer.TokenIndex, + transfer.Connector, transfer.Key, transfer.From, transfer.To, @@ -133,6 +136,7 @@ func (s *SQLCommon) tokenTransferResult(ctx context.Context, row *sql.Rows) (*ff &transfer.LocalID, &transfer.PoolProtocolID, &transfer.TokenIndex, + &transfer.Connector, &transfer.Key, &transfer.From, &transfer.To, diff --git a/internal/database/sqlcommon/tokentransfer_sql_test.go b/internal/database/sqlcommon/tokentransfer_sql_test.go index a355c31a8d..93c70f5b2d 100644 --- a/internal/database/sqlcommon/tokentransfer_sql_test.go +++ b/internal/database/sqlcommon/tokentransfer_sql_test.go @@ -40,6 +40,7 @@ func TestTokenTransferE2EWithDB(t *testing.T) { Type: fftypes.TokenTransferTypeTransfer, PoolProtocolID: "F1", TokenIndex: "1", + Connector: "erc1155", From: "0x01", To: "0x02", ProtocolID: "12345", diff --git a/internal/events/tokens_transferred.go b/internal/events/tokens_transferred.go index 82d1966857..3a2377ba2b 100644 --- a/internal/events/tokens_transferred.go +++ b/internal/events/tokens_transferred.go @@ -119,22 +119,23 @@ func (em *eventManager) TokensTransferred(tk tokens.Plugin, transfer *fftypes.To balance := &fftypes.TokenBalanceChange{ PoolProtocolID: transfer.PoolProtocolID, TokenIndex: transfer.TokenIndex, + Connector: transfer.Connector, } if transfer.Type != fftypes.TokenTransferTypeMint { - balance.Identity = transfer.From + balance.Key = transfer.From balance.Amount.Int().Neg(transfer.Amount.Int()) if err := em.database.AddTokenAccountBalance(ctx, balance); err != nil { - log.L(ctx).Errorf("Failed to update account '%s' for token transfer '%s': %s", balance.Identity, transfer.ProtocolID, err) + log.L(ctx).Errorf("Failed to update account '%s' for token transfer '%s': %s", balance.Key, transfer.ProtocolID, err) return err } } if transfer.Type != fftypes.TokenTransferTypeBurn { - balance.Identity = transfer.To + balance.Key = transfer.To balance.Amount.Int().Set(transfer.Amount.Int()) if err := em.database.AddTokenAccountBalance(ctx, balance); err != nil { - log.L(ctx).Errorf("Failed to update account '%s for token transfer '%s': %s", balance.Identity, transfer.ProtocolID, err) + log.L(ctx).Errorf("Failed to update account '%s for token transfer '%s': %s", balance.Key, transfer.ProtocolID, err) return err } } diff --git a/internal/events/tokens_transferred_test.go b/internal/events/tokens_transferred_test.go index 1ca2dc0987..36544f66ca 100644 --- a/internal/events/tokens_transferred_test.go +++ b/internal/events/tokens_transferred_test.go @@ -47,13 +47,13 @@ func TestTokensTransferredSucceedWithRetries(t *testing.T) { fromBalance := &fftypes.TokenBalanceChange{ PoolProtocolID: "F1", TokenIndex: "0", - Identity: "0x1", + Key: "0x1", } fromBalance.Amount.Int().SetInt64(-1) toBalance := &fftypes.TokenBalanceChange{ PoolProtocolID: "F1", TokenIndex: "0", - Identity: "0x2", + Key: "0x2", } toBalance.Amount.Int().SetInt64(1) pool := &fftypes.TokenPool{ @@ -179,13 +179,13 @@ func TestTokensTransferredWithMessage(t *testing.T) { fromBalance := &fftypes.TokenBalanceChange{ PoolProtocolID: "F1", TokenIndex: "0", - Identity: "0x1", + Key: "0x1", } fromBalance.Amount.Int().SetInt64(-1) toBalance := &fftypes.TokenBalanceChange{ PoolProtocolID: "F1", TokenIndex: "0", - Identity: "0x2", + Key: "0x2", } toBalance.Amount.Int().SetInt64(1) pool := &fftypes.TokenPool{ diff --git a/internal/tokens/fftokens/config.go b/internal/tokens/fftokens/config.go index 8c01a935b0..66e00cea47 100644 --- a/internal/tokens/fftokens/config.go +++ b/internal/tokens/fftokens/config.go @@ -21,6 +21,6 @@ import ( "github.com/hyperledger/firefly/internal/config/wsconfig" ) -func (h *FFTokens) InitPrefix(prefix config.PrefixArray) { +func (ft *FFTokens) InitPrefix(prefix config.PrefixArray) { wsconfig.InitPrefix(prefix) } diff --git a/internal/tokens/fftokens/fftokens.go b/internal/tokens/fftokens/fftokens.go index fd353f3452..8ff6f37bd8 100644 --- a/internal/tokens/fftokens/fftokens.go +++ b/internal/tokens/fftokens/fftokens.go @@ -91,21 +91,21 @@ type transferTokens struct { Data string `json:"data,omitempty"` } -func (h *FFTokens) Name() string { +func (ft *FFTokens) Name() string { return "fftokens" } -func (h *FFTokens) Init(ctx context.Context, name string, prefix config.Prefix, callbacks tokens.Callbacks) (err error) { - h.ctx = log.WithLogField(ctx, "proto", "fftokens") - h.callbacks = callbacks - h.configuredName = name +func (ft *FFTokens) Init(ctx context.Context, name string, prefix config.Prefix, callbacks tokens.Callbacks) (err error) { + ft.ctx = log.WithLogField(ctx, "proto", "fftokens") + ft.callbacks = callbacks + ft.configuredName = name if prefix.GetString(restclient.HTTPConfigURL) == "" { return i18n.NewError(ctx, i18n.MsgMissingPluginConfig, "url", "tokens.fftokens") } - h.client = restclient.New(h.ctx, prefix) - h.capabilities = &tokens.Capabilities{} + ft.client = restclient.New(ft.ctx, prefix) + ft.capabilities = &tokens.Capabilities{} wsConfig := wsconfig.GenerateConfigFromPrefix(prefix) @@ -113,25 +113,25 @@ func (h *FFTokens) Init(ctx context.Context, name string, prefix config.Prefix, wsConfig.WSKeyPath = "/api/ws" } - h.wsconn, err = wsclient.New(ctx, wsConfig, nil) + ft.wsconn, err = wsclient.New(ctx, wsConfig, nil) if err != nil { return err } - go h.eventLoop() + go ft.eventLoop() return nil } -func (h *FFTokens) Start() error { - return h.wsconn.Connect() +func (ft *FFTokens) Start() error { + return ft.wsconn.Connect() } -func (h *FFTokens) Capabilities() *tokens.Capabilities { - return h.capabilities +func (ft *FFTokens) Capabilities() *tokens.Capabilities { + return ft.capabilities } -func (h *FFTokens) handleReceipt(ctx context.Context, data fftypes.JSONObject) error { +func (ft *FFTokens) handleReceipt(ctx context.Context, data fftypes.JSONObject) error { l := log.L(ctx) requestID := data.GetString("id") @@ -151,12 +151,13 @@ func (h *FFTokens) handleReceipt(ctx context.Context, data fftypes.JSONObject) e replyType = fftypes.OpStatusFailed } l.Infof("Tokens '%s' reply: request=%s message=%s", replyType, requestID, message) - return h.callbacks.TokensOpUpdate(h, operationID, replyType, message, data) + return ft.callbacks.TokensOpUpdate(ft, operationID, replyType, message, data) } -func (h *FFTokens) handleTokenPoolCreate(ctx context.Context, data fftypes.JSONObject) (err error) { +func (ft *FFTokens) handleTokenPoolCreate(ctx context.Context, data fftypes.JSONObject) (err error) { tokenType := data.GetString("type") protocolID := data.GetString("poolId") + standard := data.GetString("standard") // this is optional trackingID := data.GetString("trackingId") operatorAddress := data.GetString("operator") tx := data.GetObject("transaction") @@ -180,6 +181,8 @@ func (h *FFTokens) handleTokenPoolCreate(ctx context.Context, data fftypes.JSONO pool := &fftypes.TokenPool{ Type: fftypes.FFEnum(tokenType), ProtocolID: protocolID, + Standard: standard, + Connector: ft.configuredName, Key: operatorAddress, TX: fftypes.TransactionRef{ ID: txID, @@ -188,10 +191,10 @@ func (h *FFTokens) handleTokenPoolCreate(ctx context.Context, data fftypes.JSONO } // If there's an error dispatching the event, we must return the error and shutdown - return h.callbacks.TokenPoolCreated(h, pool, txHash, tx) + return ft.callbacks.TokenPoolCreated(ft, pool, txHash, tx) } -func (h *FFTokens) handleTokenTransfer(ctx context.Context, t fftypes.TokenTransferType, data fftypes.JSONObject) (err error) { +func (ft *FFTokens) handleTokenTransfer(ctx context.Context, t fftypes.TokenTransferType, data fftypes.JSONObject) (err error) { tokenIndex := data.GetString("tokenIndex") poolProtocolID := data.GetString("poolId") operatorAddress := data.GetString("operator") @@ -243,6 +246,7 @@ func (h *FFTokens) handleTokenTransfer(ctx context.Context, t fftypes.TokenTrans Type: t, PoolProtocolID: poolProtocolID, TokenIndex: tokenIndex, + Connector: ft.configuredName, From: fromAddress, To: toAddress, ProtocolID: txHash, @@ -261,19 +265,19 @@ func (h *FFTokens) handleTokenTransfer(ctx context.Context, t fftypes.TokenTrans } // If there's an error dispatching the event, we must return the error and shutdown - return h.callbacks.TokensTransferred(h, transfer, txHash, tx) + return ft.callbacks.TokensTransferred(ft, transfer, txHash, tx) } -func (h *FFTokens) eventLoop() { - defer h.wsconn.Close() - l := log.L(h.ctx).WithField("role", "event-loop") - ctx := log.WithLogger(h.ctx, l) +func (ft *FFTokens) eventLoop() { + defer ft.wsconn.Close() + l := log.L(ft.ctx).WithField("role", "event-loop") + ctx := log.WithLogger(ft.ctx, l) for { select { case <-ctx.Done(): l.Debugf("Event loop exiting (context cancelled)") return - case msgBytes, ok := <-h.wsconn.Receive(): + case msgBytes, ok := <-ft.wsconn.Receive(): if !ok { l.Debugf("Event loop exiting (receive channel closed)") return @@ -288,15 +292,15 @@ func (h *FFTokens) eventLoop() { l.Debugf("Received %s event %s", msg.Event, msg.ID) switch msg.Event { case messageReceipt: - err = h.handleReceipt(ctx, msg.Data) + err = ft.handleReceipt(ctx, msg.Data) case messageTokenPool: - err = h.handleTokenPoolCreate(ctx, msg.Data) + err = ft.handleTokenPoolCreate(ctx, msg.Data) case messageTokenMint: - err = h.handleTokenTransfer(ctx, fftypes.TokenTransferTypeMint, msg.Data) + err = ft.handleTokenTransfer(ctx, fftypes.TokenTransferTypeMint, msg.Data) case messageTokenBurn: - err = h.handleTokenTransfer(ctx, fftypes.TokenTransferTypeBurn, msg.Data) + err = ft.handleTokenTransfer(ctx, fftypes.TokenTransferTypeBurn, msg.Data) case messageTokenTransfer: - err = h.handleTokenTransfer(ctx, fftypes.TokenTransferTypeTransfer, msg.Data) + err = ft.handleTokenTransfer(ctx, fftypes.TokenTransferTypeTransfer, msg.Data) default: l.Errorf("Message unexpected: %s", msg.Event) } @@ -309,7 +313,7 @@ func (h *FFTokens) eventLoop() { "id": msg.ID, }, }) - err = h.wsconn.Send(ctx, ack) + err = ft.wsconn.Send(ctx, ack) } if err != nil { @@ -320,8 +324,8 @@ func (h *FFTokens) eventLoop() { } } -func (h *FFTokens) CreateTokenPool(ctx context.Context, operationID *fftypes.UUID, pool *fftypes.TokenPool) error { - res, err := h.client.R().SetContext(ctx). +func (ft *FFTokens) CreateTokenPool(ctx context.Context, operationID *fftypes.UUID, pool *fftypes.TokenPool) error { + res, err := ft.client.R().SetContext(ctx). SetBody(&createPool{ Type: pool.Type, RequestID: operationID.String(), @@ -335,8 +339,8 @@ func (h *FFTokens) CreateTokenPool(ctx context.Context, operationID *fftypes.UUI return nil } -func (h *FFTokens) MintTokens(ctx context.Context, operationID *fftypes.UUID, mint *fftypes.TokenTransfer) error { - res, err := h.client.R().SetContext(ctx). +func (ft *FFTokens) MintTokens(ctx context.Context, operationID *fftypes.UUID, mint *fftypes.TokenTransfer) error { + res, err := ft.client.R().SetContext(ctx). SetBody(&mintTokens{ PoolID: mint.PoolProtocolID, To: mint.To, @@ -351,8 +355,8 @@ func (h *FFTokens) MintTokens(ctx context.Context, operationID *fftypes.UUID, mi return nil } -func (h *FFTokens) BurnTokens(ctx context.Context, operationID *fftypes.UUID, burn *fftypes.TokenTransfer) error { - res, err := h.client.R().SetContext(ctx). +func (ft *FFTokens) BurnTokens(ctx context.Context, operationID *fftypes.UUID, burn *fftypes.TokenTransfer) error { + res, err := ft.client.R().SetContext(ctx). SetBody(&burnTokens{ PoolID: burn.PoolProtocolID, TokenIndex: burn.TokenIndex, @@ -368,8 +372,8 @@ func (h *FFTokens) BurnTokens(ctx context.Context, operationID *fftypes.UUID, bu return nil } -func (h *FFTokens) TransferTokens(ctx context.Context, operationID *fftypes.UUID, transfer *fftypes.TokenTransfer) error { - res, err := h.client.R().SetContext(ctx). +func (ft *FFTokens) TransferTokens(ctx context.Context, operationID *fftypes.UUID, transfer *fftypes.TokenTransfer) error { + res, err := ft.client.R().SetContext(ctx). SetBody(&transferTokens{ PoolID: transfer.PoolProtocolID, TokenIndex: transfer.TokenIndex, diff --git a/pkg/database/plugin.go b/pkg/database/plugin.go index ea2f466b9a..689c25fa65 100644 --- a/pkg/database/plugin.go +++ b/pkg/database/plugin.go @@ -764,6 +764,7 @@ var TokenPoolQueryFactory = &queryFields{ "type": &StringField{}, "namespace": &StringField{}, "name": &StringField{}, + "standard": &StringField{}, "protocolid": &StringField{}, "key": &StringField{}, "symbol": &StringField{}, @@ -775,8 +776,10 @@ var TokenPoolQueryFactory = &queryFields{ var TokenAccountQueryFactory = &queryFields{ "poolprotocolid": &StringField{}, "tokenindex": &StringField{}, - "identity": &StringField{}, + "connector": &StringField{}, + "key": &StringField{}, "balance": &Int64Field{}, + "updated": &TimeField{}, } // TokenTransferQueryFactory filter fields for token transfers @@ -784,6 +787,7 @@ var TokenTransferQueryFactory = &queryFields{ "localid": &StringField{}, "poolprotocolid": &StringField{}, "tokenindex": &StringField{}, + "connector": &StringField{}, "key": &StringField{}, "from": &StringField{}, "to": &StringField{}, diff --git a/pkg/fftypes/tokenaccount.go b/pkg/fftypes/tokenaccount.go index 4b6217d627..9174ceffdd 100644 --- a/pkg/fftypes/tokenaccount.go +++ b/pkg/fftypes/tokenaccount.go @@ -17,10 +17,12 @@ package fftypes type TokenAccount struct { - PoolProtocolID string `json:"poolProtocolId,omitempty"` - TokenIndex string `json:"tokenIndex,omitempty"` - Identity string `json:"identity,omitempty"` - Balance BigInt `json:"balance"` + PoolProtocolID string `json:"poolProtocolId,omitempty"` + TokenIndex string `json:"tokenIndex,omitempty"` + Connector string `json:"connector,omitempty"` + Key string `json:"key,omitempty"` + Balance BigInt `json:"balance"` + Updated *FFTime `json:"updated,omitempty"` } func TokenAccountIdentifier(protocolID, tokenIndex, identity string) string { @@ -28,12 +30,13 @@ func TokenAccountIdentifier(protocolID, tokenIndex, identity string) string { } func (t *TokenAccount) Identifier() string { - return TokenAccountIdentifier(t.PoolProtocolID, t.TokenIndex, t.Identity) + return TokenAccountIdentifier(t.PoolProtocolID, t.TokenIndex, t.Key) } type TokenBalanceChange struct { PoolProtocolID string TokenIndex string - Identity string + Connector string + Key string Amount BigInt } diff --git a/pkg/fftypes/tokenaccount_test.go b/pkg/fftypes/tokenaccount_test.go index 5328ce96fd..bf40fa5009 100644 --- a/pkg/fftypes/tokenaccount_test.go +++ b/pkg/fftypes/tokenaccount_test.go @@ -26,7 +26,7 @@ func TestTokenAccountIdentifier(t *testing.T) { account := &TokenAccount{ PoolProtocolID: "123", TokenIndex: "1", - Identity: "0x00", + Key: "0x00", } assert.Equal(t, "123:1:0x00", account.Identifier()) } diff --git a/pkg/fftypes/tokenpool.go b/pkg/fftypes/tokenpool.go index c41d4a46a4..20137abbc8 100644 --- a/pkg/fftypes/tokenpool.go +++ b/pkg/fftypes/tokenpool.go @@ -32,6 +32,7 @@ type TokenPool struct { Type TokenType `json:"type" ffenum:"tokentype"` Namespace string `json:"namespace,omitempty"` Name string `json:"name,omitempty"` + Standard string `json:"standard,omitempty"` ProtocolID string `json:"protocolId,omitempty"` Key string `json:"key,omitempty"` Symbol string `json:"symbol,omitempty"` diff --git a/pkg/fftypes/tokentransfer.go b/pkg/fftypes/tokentransfer.go index 22136cf30a..47e2c437b9 100644 --- a/pkg/fftypes/tokentransfer.go +++ b/pkg/fftypes/tokentransfer.go @@ -29,6 +29,7 @@ type TokenTransfer struct { LocalID *UUID `json:"localId,omitempty"` PoolProtocolID string `json:"poolProtocolId,omitempty"` TokenIndex string `json:"tokenIndex,omitempty"` + Connector string `json:"connector,omitempty"` Key string `json:"key,omitempty"` From string `json:"from,omitempty"` To string `json:"to,omitempty"` diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 416a2082a1..f2d715170d 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -130,8 +130,9 @@ func validateReceivedMessages(ts *testState, client *resty.Client, msgType fftyp } func validateAccountBalances(t *testing.T, client *resty.Client, poolName, tokenIndex string, balances map[string]int64) { - for identity, balance := range balances { - account := GetTokenAccount(t, client, poolName, tokenIndex, identity) + for key, balance := range balances { + account := GetTokenAccount(t, client, poolName, tokenIndex, key) + assert.Equal(t, "erc1155", account.Connector) assert.Equal(t, balance, account.Balance.Int().Int64()) } } @@ -505,6 +506,7 @@ func TestE2ETokenPool(t *testing.T) { pools = GetTokenPools(t, ts.client1, ts.startTime) assert.Equal(t, 1, len(pools)) assert.Equal(t, "default", pools[0].Namespace) + assert.Equal(t, "erc1155", pools[0].Connector) assert.Equal(t, poolName, pools[0].Name) assert.Equal(t, fftypes.TokenTypeFungible, pools[0].Type) @@ -512,6 +514,7 @@ func TestE2ETokenPool(t *testing.T) { pools = GetTokenPools(t, ts.client1, ts.startTime) assert.Equal(t, 1, len(pools)) assert.Equal(t, "default", pools[0].Namespace) + assert.Equal(t, "erc1155", pools[0].Connector) assert.Equal(t, poolName, pools[0].Name) assert.Equal(t, fftypes.TokenTypeFungible, pools[0].Type) @@ -522,6 +525,7 @@ func TestE2ETokenPool(t *testing.T) { <-received1 transfers := GetTokenTransfers(t, ts.client1, poolName) assert.Equal(t, 1, len(transfers)) + assert.Equal(t, "erc1155", transfers[0].Connector) assert.Equal(t, fftypes.TokenTransferTypeMint, transfers[0].Type) assert.Equal(t, int64(1), transfers[0].Amount.Int().Int64()) validateAccountBalances(t, ts.client1, poolName, "", map[string]int64{ @@ -531,6 +535,7 @@ func TestE2ETokenPool(t *testing.T) { <-received2 transfers = GetTokenTransfers(t, ts.client2, poolName) assert.Equal(t, 1, len(transfers)) + assert.Equal(t, "erc1155", transfers[0].Connector) assert.Equal(t, fftypes.TokenTransferTypeMint, transfers[0].Type) assert.Equal(t, int64(1), transfers[0].Amount.Int().Int64()) validateAccountBalances(t, ts.client2, poolName, "", map[string]int64{ @@ -546,6 +551,7 @@ func TestE2ETokenPool(t *testing.T) { <-received1 transfers = GetTokenTransfers(t, ts.client1, poolName) assert.Equal(t, 2, len(transfers)) + assert.Equal(t, "erc1155", transfers[0].Connector) assert.Equal(t, fftypes.TokenTransferTypeTransfer, transfers[0].Type) assert.Equal(t, int64(1), transfers[0].Amount.Int().Int64()) validateAccountBalances(t, ts.client1, poolName, "", map[string]int64{ @@ -556,6 +562,7 @@ func TestE2ETokenPool(t *testing.T) { <-received2 transfers = GetTokenTransfers(t, ts.client2, poolName) assert.Equal(t, 2, len(transfers)) + assert.Equal(t, "erc1155", transfers[0].Connector) assert.Equal(t, fftypes.TokenTransferTypeTransfer, transfers[0].Type) assert.Equal(t, int64(1), transfers[0].Amount.Int().Int64()) validateAccountBalances(t, ts.client2, poolName, "", map[string]int64{ @@ -570,6 +577,7 @@ func TestE2ETokenPool(t *testing.T) { <-received2 transfers = GetTokenTransfers(t, ts.client2, poolName) assert.Equal(t, 3, len(transfers)) + assert.Equal(t, "erc1155", transfers[0].Connector) assert.Equal(t, fftypes.TokenTransferTypeBurn, transfers[0].Type) assert.Equal(t, int64(1), transfers[0].Amount.Int().Int64()) validateAccountBalances(t, ts.client2, poolName, "", map[string]int64{ @@ -580,6 +588,7 @@ func TestE2ETokenPool(t *testing.T) { <-received1 transfers = GetTokenTransfers(t, ts.client1, poolName) assert.Equal(t, 3, len(transfers)) + assert.Equal(t, "erc1155", transfers[0].Connector) assert.Equal(t, fftypes.TokenTransferTypeBurn, transfers[0].Type) assert.Equal(t, int64(1), transfers[0].Amount.Int().Int64()) validateAccountBalances(t, ts.client1, poolName, "", map[string]int64{ diff --git a/test/e2e/restclient.go b/test/e2e/restclient.go index 1996caa675..3582123b2d 100644 --- a/test/e2e/restclient.go +++ b/test/e2e/restclient.go @@ -375,16 +375,16 @@ func GetTokenTransfers(t *testing.T, client *resty.Client, poolName string) (tra return transfers } -func GetTokenAccount(t *testing.T, client *resty.Client, poolName, tokenIndex, identity string) (account *fftypes.TokenAccount) { +func GetTokenAccount(t *testing.T, client *resty.Client, poolName, tokenIndex, key string) (account *fftypes.TokenAccount) { var accounts []*fftypes.TokenAccount path := fmt.Sprintf(urlTokenAccounts, poolName) resp, err := client.R(). SetQueryParam("tokenIndex", tokenIndex). - SetQueryParam("identity", identity). + SetQueryParam("key", key). SetResult(&accounts). Get(path) require.NoError(t, err) require.Equal(t, 200, resp.StatusCode(), "GET %s [%d]: %s", path, resp.StatusCode(), resp.String()) - require.Greater(t, len(accounts), 0) + require.Equal(t, len(accounts), 1) return accounts[0] }