Skip to content

Commit 79b171c

Browse files
committed
feat: Add version-based filtering for NFDs
Introduced NFD filtering based on major version constraints (`minMajorVersion` and `maxMajorVersion`) with appropriate documentation and configuration updates. chore(*): upgraded `go` to 1.24 and updated key dependencies (`algorand-sdk`, `mailgun/holster`, `golang.org/x/crypto`, etc.).
1 parent 22d93c5 commit 79b171c

6 files changed

Lines changed: 53 additions & 8 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ Some of these options conflict with eachother if specified together.
104104
"segmentsOfRoot": "orange.algo",
105105
"allowDuplicateAccounts": true,
106106
"onlyRoots": false,
107+
"minMajorVersion": 3,
108+
"maxMajorVersion": 3,
107109
"randomNFDs": {
108110
"count": 100
109111
},
@@ -127,6 +129,8 @@ Some of these options conflict with eachother if specified together.
127129
- The owner of each NFD is used and if allowDuplicateAccounts is false, then only unique owners are chosen amongst the NFDs (picking an artbirary NFD for that owner)
128130
- `onlyRoots`: Determines whether only root NFDs are allowed.
129131
- If specified, only roots are chosen with segments being skipped.
132+
- `minMajorVersion`: If specified, only NFDs with a major version >= this value are considered.
133+
- `maxMajorVersion`: If specified, only NFDs with a major version <= this value are considered.` Using both could be used for only sending to 2.x, or 3.x.
130134
- `randomNFDs`:
131135
- `count`: If specified, this is the number of NFDS to choose randomly from the total list. ie: All segments of root X, but only pick 100 random recipients by specifying a count here.
132136
- `verifiedRequirements`: An optional array of verified field names. If specified, the destination NFD must have ALL of the specified verified fields.

go.mod

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
module github.com/TxnLab/batch-asset-send
22

3-
go 1.23
3+
go 1.24
44

55
require (
6-
github.com/algorand/go-algorand-sdk/v2 v2.6.0
6+
github.com/algorand/go-algorand-sdk/v2 v2.10.0
77
github.com/antihax/optional v1.0.0
88
github.com/joho/godotenv v1.5.1
9-
github.com/mailgun/holster/v4 v4.20.3
9+
github.com/mailgun/holster/v4 v4.21.0
1010
github.com/ssgreg/repeat v1.5.1
11-
golang.org/x/crypto v0.28.0
12-
golang.org/x/oauth2 v0.23.0
13-
golang.org/x/time v0.7.0
11+
golang.org/x/crypto v0.41.0
12+
golang.org/x/oauth2 v0.30.0
13+
golang.org/x/time v0.12.0
1414
)
1515

1616
require (
17-
github.com/algorand/avm-abi v0.1.1 // indirect
17+
github.com/algorand/avm-abi v0.2.0 // indirect
1818
github.com/algorand/go-codec/codec v1.1.10 // indirect
1919
github.com/google/go-cmp v0.6.0 // indirect
20-
github.com/google/go-querystring v1.0.0 // indirect
20+
github.com/google/go-querystring v1.1.0 // indirect
2121
)

go.sum

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ github.com/ahmetb/go-linq v3.0.0+incompatible h1:qQkjjOXKrKOTy83X8OpRmnKflXKQIL/
22
github.com/ahmetb/go-linq v3.0.0+incompatible/go.mod h1:PFffvbdbtw+QTB0WKRP0cNht7vnCfnGlEpak/DVg5cY=
33
github.com/algorand/avm-abi v0.1.1 h1:dbyQKzXiyaEbzpmqXFB30yAhyqseBsyqXTyZbNbkh2Y=
44
github.com/algorand/avm-abi v0.1.1/go.mod h1:+CgwM46dithy850bpTeHh9MC99zpn2Snirb3QTl2O/g=
5+
github.com/algorand/avm-abi v0.2.0/go.mod h1:+CgwM46dithy850bpTeHh9MC99zpn2Snirb3QTl2O/g=
56
github.com/algorand/go-algorand-sdk/v2 v2.6.0 h1:pfL8lloEi26l6PwAFicmPUguWgKpy1eZZTMlQcci5h0=
67
github.com/algorand/go-algorand-sdk/v2 v2.6.0/go.mod h1:4ayerzjoWChm3kuVhbgFgURTbaYTtlj0c41eP3av5lw=
8+
github.com/algorand/go-algorand-sdk/v2 v2.10.0 h1:4UW/UwW51ugNVQKclvTkc42gicRXSt5f+YAcTufLv/0=
9+
github.com/algorand/go-algorand-sdk/v2 v2.10.0/go.mod h1:D6iKT87/N6ajNpN7uMYPC9/RsOo2BbxnDfvh81E3hOM=
710
github.com/algorand/go-codec/codec v1.1.10 h1:zmWYU1cp64jQVTOG8Tw8wa+k0VfwgXIPbnDfiVa+5QA=
811
github.com/algorand/go-codec/codec v1.1.10/go.mod h1:YkEx5nmr/zuCeaDYOIhlDg92Lxju8tj2d2NrYqP7g7k=
912
github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
@@ -13,14 +16,18 @@ github.com/chrismcguire/gobberish v0.0.0-20150821175641-1d8adb509a0e/go.mod h1:6
1316
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1417
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1518
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
19+
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
1620
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
1721
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
1822
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
1923
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
24+
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
2025
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
2126
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
2227
github.com/mailgun/holster/v4 v4.20.3 h1:FwHxBvuoWEqEpZGeNCLuk/oAHyNs3+ksGoCW0qbiHyo=
2328
github.com/mailgun/holster/v4 v4.20.3/go.mod h1:HuFVoS8qOhceEBL4czXnVzp0bQrrIkLeX30IAll5hQ0=
29+
github.com/mailgun/holster/v4 v4.21.0 h1:EH3fwKEGv56WA5gUwxjOTqZbeILY+oJ/VWEo1xku7t8=
30+
github.com/mailgun/holster/v4 v4.21.0/go.mod h1:G06Q741dj+zsH1WFrmoFvih3LtaocvBIoNtxITdWEtg=
2431
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
2532
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
2633
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -38,12 +45,16 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
3845
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
3946
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
4047
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
48+
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
49+
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
4150
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
4251
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
4352
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
4453
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
4554
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
4655
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
56+
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
57+
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
4758
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4859
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4960
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -60,11 +71,14 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
6071
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
6172
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
6273
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
74+
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
75+
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
6376
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
6477
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
6578
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
6679
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
6780
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
81+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
6882
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
6983
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
7084
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

nfd-helpers.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,19 @@ func IsContractVersionAtLeast(version string, major, minor int) bool {
4141
return false
4242
}
4343

44+
func GetContractMajorVersion(version string) int {
45+
majMinReg := regexp.MustCompile(`^(?P<major>\d+)\.(?P<minor>\d+)`)
46+
matches := majMinReg.FindStringSubmatch(version)
47+
if matches == nil || len(matches) != 3 {
48+
return 0
49+
}
50+
var contractMajor int
51+
if val := matches[majMinReg.SubexpIndex("major")]; val != "" {
52+
contractMajor, _ = strconv.Atoi(val)
53+
}
54+
return contractMajor
55+
}
56+
4457
// IsVaultAutoOptInLockedForSender returns true if the specified 'sender' address
4558
// would be allowed to send to the NFDs vault. This is basically an off-chain
4659
// validation of what the contract itself will do, to save some trouble and skip sending to a vault that won't

recips.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,16 @@ func filterNfds(config *BatchSendConfig, records []*nfdapi.NfdRecord) ([]*nfdapi
176176
continue
177177
}
178178
}
179+
if config.Destination.MinMajorVersion != 0 {
180+
if !IsContractVersionAtLeast(nfd.Properties.Internal["ver"], config.Destination.MinMajorVersion, 0) {
181+
continue
182+
}
183+
}
184+
if config.Destination.MaxMajorVersion != 0 {
185+
if GetContractMajorVersion(nfd.Properties.Internal["ver"]) > config.Destination.MaxMajorVersion {
186+
continue
187+
}
188+
}
179189

180190
verifiedProps := nfd.Properties.Verified
181191
if len(verifiedProps) > 0 {

sendconfiguration.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ type DestinationChoice struct {
4747

4848
SendToVaults bool `json:"sendToVaults"`
4949

50+
// Whether to limit the send to only those NFDs that have a version between these two numbers (each optional)
51+
MinMajorVersion int `json:"minMajorVersion"`
52+
MaxMajorVersion int `json:"maxMajorVersion"`
53+
5054
// Only send if v.XXXX is present in NFD (ie: verifiedRequirements: ["twitter"] would require v.twitter to be set)
5155
VerifiedRequirements []string `json:"verifiedRequirements,omitempty"`
5256

0 commit comments

Comments
 (0)