diff --git a/api/openapi.json b/api/openapi.json index 1c591094..01e72353 100644 --- a/api/openapi.json +++ b/api/openapi.json @@ -2465,7 +2465,8 @@ "items": { "enum": [ "getgems", - "tonkeeper" + "tonkeeper", + "ton.diamonds" ], "example": "getgems", "type": "string" @@ -3436,8 +3437,7 @@ "items": { "properties": { "account": { - "$ref": "#/components/schemas/AccountAddress", - "deprecated": true + "$ref": "#/components/schemas/AccountAddress" }, "jetton": { "$ref": "#/components/schemas/JettonPreview" diff --git a/api/openapi.yml b/api/openapi.yml index 2c1c0b00..0a0dc88e 100644 --- a/api/openapi.yml +++ b/api/openapi.yml @@ -3352,6 +3352,7 @@ components: enum: - getgems - tonkeeper + - ton.diamonds NftItems: type: object required: diff --git a/client/oas_json_gen.go b/client/oas_json_gen.go index 479f185f..67cf0b2a 100644 --- a/client/oas_json_gen.go +++ b/client/oas_json_gen.go @@ -15520,6 +15520,8 @@ func (s *NftItemApprovedByItem) Decode(d *jx.Decoder) error { *s = NftItemApprovedByItemGetgems case NftItemApprovedByItemTonkeeper: *s = NftItemApprovedByItemTonkeeper + case NftItemApprovedByItemTonDiamonds: + *s = NftItemApprovedByItemTonDiamonds default: *s = NftItemApprovedByItem(v) } diff --git a/client/oas_schemas_gen.go b/client/oas_schemas_gen.go index 8016fcde..93e7d55d 100644 --- a/client/oas_schemas_gen.go +++ b/client/oas_schemas_gen.go @@ -5244,8 +5244,9 @@ func (s *NftItem) SetApprovedBy(val []NftItemApprovedByItem) { type NftItemApprovedByItem string const ( - NftItemApprovedByItemGetgems NftItemApprovedByItem = "getgems" - NftItemApprovedByItemTonkeeper NftItemApprovedByItem = "tonkeeper" + NftItemApprovedByItemGetgems NftItemApprovedByItem = "getgems" + NftItemApprovedByItemTonkeeper NftItemApprovedByItem = "tonkeeper" + NftItemApprovedByItemTonDiamonds NftItemApprovedByItem = "ton.diamonds" ) // MarshalText implements encoding.TextMarshaler. @@ -5255,6 +5256,8 @@ func (s NftItemApprovedByItem) MarshalText() ([]byte, error) { return []byte(s), nil case NftItemApprovedByItemTonkeeper: return []byte(s), nil + case NftItemApprovedByItemTonDiamonds: + return []byte(s), nil default: return nil, errors.Errorf("invalid value: %q", s) } @@ -5269,6 +5272,9 @@ func (s *NftItemApprovedByItem) UnmarshalText(data []byte) error { case NftItemApprovedByItemTonkeeper: *s = NftItemApprovedByItemTonkeeper return nil + case NftItemApprovedByItemTonDiamonds: + *s = NftItemApprovedByItemTonDiamonds + return nil default: return errors.Errorf("invalid value: %q", data) } diff --git a/client/oas_validators_gen.go b/client/oas_validators_gen.go index b1ae074c..c7e7e26e 100644 --- a/client/oas_validators_gen.go +++ b/client/oas_validators_gen.go @@ -1899,6 +1899,8 @@ func (s NftItemApprovedByItem) Validate() error { return nil case "tonkeeper": return nil + case "ton.diamonds": + return nil default: return errors.Errorf("invalid value: %v", s) } diff --git a/pkg/addressbook/addressbook.go b/pkg/addressbook/addressbook.go index d0beea57..6862dece 100644 --- a/pkg/addressbook/addressbook.go +++ b/pkg/addressbook/addressbook.go @@ -12,6 +12,8 @@ import ( "github.com/shopspring/decimal" "github.com/shurcooL/graphql" + "github.com/tonkeeper/opentonapi/pkg/oas" + "github.com/tonkeeper/opentonapi/pkg/references" "github.com/tonkeeper/tongo" "go.uber.org/zap" "golang.org/x/exp/maps" @@ -66,7 +68,7 @@ type KnownCollection struct { MaxItems int64 `json:"max_items"` Websites []string `json:"websites,omitempty"` Social []string `json:"social,omitempty"` - Approvers []string + Approvers []oas.NftItemApprovedByItem } type Option func(o *Options) @@ -211,6 +213,7 @@ func NewAddressBook(logger *zap.Logger, addressPath, jettonPath, collectionPath }() go book.getGGWhitelist(logger) + go book.getTonDiamondsWhitelist() return book } @@ -292,8 +295,10 @@ func (b *Book) refreshStonfiJettons(logger *zap.Logger) { } } -func unique(approvers []string) []string { - sort.Strings(approvers) +func unique(approvers []oas.NftItemApprovedByItem) []oas.NftItemApprovedByItem { + sort.Slice(approvers, func(i, j int) bool { + return approvers[i] < approvers[j] + }) return slices.Compact(approvers) } @@ -315,12 +320,12 @@ func (b *Book) refreshCollections(logger *zap.Logger, collectionPath string) { if !ok { // this is a new item, so we only add tonkeeper as approver. item.Address = accountID.ToRaw() - item.Approvers = unique(append(item.Approvers, "tonkeeper")) + item.Approvers = unique(append(item.Approvers, oas.NftItemApprovedByItemTonkeeper)) b.collections[accountID] = item continue } // this is an existing item, so we merge approvers and remove duplicates adding tonkeeper. - item.Approvers = unique(append(append(currentCollection.Approvers, item.Approvers...), "tonkeeper")) + item.Approvers = unique(append(append(currentCollection.Approvers, item.Approvers...), oas.NftItemApprovedByItemTonkeeper)) b.collections[accountID] = item } } @@ -376,7 +381,24 @@ func (b *Book) getGGWhitelist(logger *zap.Logger) { b.mu.Lock() for _, account := range addresses { collection := b.collections[account] - collection.Approvers = unique(append(collection.Approvers, "getgems")) + collection.Approvers = unique(append(collection.Approvers, oas.NftItemApprovedByItemGetgems)) + b.collections[account] = collection + } + b.mu.Unlock() + return + } +} + +func (b *Book) getTonDiamondsWhitelist() { + for { + if len(b.GetKnownCollections()) == 0 { + time.Sleep(time.Second * 10) + continue + } + b.mu.Lock() + for _, account := range references.TonDiamondsCollections { + collection := b.collections[account] + collection.Approvers = unique(append(collection.Approvers, oas.NftItemApprovedByItemTonDiamonds)) b.collections[account] = collection } b.mu.Unlock() diff --git a/pkg/addressbook/addressbook_test.go b/pkg/addressbook/addressbook_test.go index 87fa0b35..8eb6b5fd 100644 --- a/pkg/addressbook/addressbook_test.go +++ b/pkg/addressbook/addressbook_test.go @@ -3,18 +3,20 @@ package addressbook import ( "reflect" "testing" + + "github.com/tonkeeper/opentonapi/pkg/oas" ) func Test_unique(t *testing.T) { tests := []struct { name string - approvers []string - want []string + approvers []oas.NftItemApprovedByItem + want []oas.NftItemApprovedByItem }{ { name: "all good", - approvers: []string{"tonkeeper", "getgems", "getgems", "tonkeeper"}, - want: []string{"getgems", "tonkeeper"}, + approvers: []oas.NftItemApprovedByItem{oas.NftItemApprovedByItemTonkeeper, oas.NftItemApprovedByItemGetgems, oas.NftItemApprovedByItemGetgems, oas.NftItemApprovedByItemTonkeeper}, + want: []oas.NftItemApprovedByItem{oas.NftItemApprovedByItemGetgems, oas.NftItemApprovedByItemTonkeeper}, }, } for _, tt := range tests { @@ -23,7 +25,6 @@ func Test_unique(t *testing.T) { if !reflect.DeepEqual(newList, tt.want) { t.Errorf("unique() = %v, want %v", newList, tt.want) } - }) } } diff --git a/pkg/api/nft_converters.go b/pkg/api/nft_converters.go index bbc4b6ef..c0facc74 100644 --- a/pkg/api/nft_converters.go +++ b/pkg/api/nft_converters.go @@ -51,12 +51,7 @@ func convertNFT(ctx context.Context, item core.NftItem, book addressBook, metaCa if item.CollectionAddress != nil { if cc, prs := book.GetCollectionInfoByAddress(*item.CollectionAddress); prs { for _, a := range cc.Approvers { - switch a { - case "tonkeeper": - i.ApprovedBy = append(i.ApprovedBy, oas.NftItemApprovedByItemTonkeeper) - case "getgems": - i.ApprovedBy = append(i.ApprovedBy, oas.NftItemApprovedByItemGetgems) - } + i.ApprovedBy = append(i.ApprovedBy, a) } } cInfo, _ := metaCache.getCollectionMeta(ctx, *item.CollectionAddress) diff --git a/pkg/oas/oas_json_gen.go b/pkg/oas/oas_json_gen.go index 46c26576..7756c2bc 100644 --- a/pkg/oas/oas_json_gen.go +++ b/pkg/oas/oas_json_gen.go @@ -15520,6 +15520,8 @@ func (s *NftItemApprovedByItem) Decode(d *jx.Decoder) error { *s = NftItemApprovedByItemGetgems case NftItemApprovedByItemTonkeeper: *s = NftItemApprovedByItemTonkeeper + case NftItemApprovedByItemTonDiamonds: + *s = NftItemApprovedByItemTonDiamonds default: *s = NftItemApprovedByItem(v) } diff --git a/pkg/oas/oas_schemas_gen.go b/pkg/oas/oas_schemas_gen.go index dfcb5af4..a20bdfb1 100644 --- a/pkg/oas/oas_schemas_gen.go +++ b/pkg/oas/oas_schemas_gen.go @@ -5244,8 +5244,9 @@ func (s *NftItem) SetApprovedBy(val []NftItemApprovedByItem) { type NftItemApprovedByItem string const ( - NftItemApprovedByItemGetgems NftItemApprovedByItem = "getgems" - NftItemApprovedByItemTonkeeper NftItemApprovedByItem = "tonkeeper" + NftItemApprovedByItemGetgems NftItemApprovedByItem = "getgems" + NftItemApprovedByItemTonkeeper NftItemApprovedByItem = "tonkeeper" + NftItemApprovedByItemTonDiamonds NftItemApprovedByItem = "ton.diamonds" ) // MarshalText implements encoding.TextMarshaler. @@ -5255,6 +5256,8 @@ func (s NftItemApprovedByItem) MarshalText() ([]byte, error) { return []byte(s), nil case NftItemApprovedByItemTonkeeper: return []byte(s), nil + case NftItemApprovedByItemTonDiamonds: + return []byte(s), nil default: return nil, errors.Errorf("invalid value: %q", s) } @@ -5269,6 +5272,9 @@ func (s *NftItemApprovedByItem) UnmarshalText(data []byte) error { case NftItemApprovedByItemTonkeeper: *s = NftItemApprovedByItemTonkeeper return nil + case NftItemApprovedByItemTonDiamonds: + *s = NftItemApprovedByItemTonDiamonds + return nil default: return errors.Errorf("invalid value: %q", data) } diff --git a/pkg/oas/oas_validators_gen.go b/pkg/oas/oas_validators_gen.go index 149aab9e..43ce8485 100644 --- a/pkg/oas/oas_validators_gen.go +++ b/pkg/oas/oas_validators_gen.go @@ -1899,6 +1899,8 @@ func (s NftItemApprovedByItem) Validate() error { return nil case "tonkeeper": return nil + case "ton.diamonds": + return nil default: return errors.Errorf("invalid value: %v", s) } diff --git a/pkg/references/collections.go b/pkg/references/collections.go new file mode 100644 index 00000000..06850dce --- /dev/null +++ b/pkg/references/collections.go @@ -0,0 +1,13 @@ +package references + +import ( + "github.com/tonkeeper/tongo" +) + +var TonDiamondsCollections = []tongo.AccountID{ + tongo.MustParseAccountID("EQAG2BH0JlmFkbMrLEnyn2bIITaOSssd4WdisE4BdFMkZbir"), + tongo.MustParseAccountID("EQB8D8A9OoDoRmL7qVbUBrd_po9vNKcl44HCSw6b-c3nvcj9"), + tongo.MustParseAccountID("EQD7eDxP_wLX18kr8uyYfs6srlgoNMfRbXNYM8dmMXT2vxwk"), + tongo.MustParseAccountID("EQDia1dY5G5_J4LDaqW9xPyLw2T3s25y6U1W1nSkQ3BRzM7x"), + tongo.MustParseAccountID("EQCoPMFxArXwkKO9zH6IU-ZJ0ahFU2nih9rPvN7_YWcxRmhb"), +}