-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from portto/spl-name-service
feat: support spl name service query
- Loading branch information
Showing
5 changed files
with
210 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package nsprog | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/portto/solana-go-sdk/common" | ||
) | ||
|
||
type NameRecordHeader struct { | ||
ParentName common.PublicKey | ||
Owner common.PublicKey | ||
Class common.PublicKey | ||
Data []byte | ||
} | ||
|
||
func NameRecordHeaderFromData(data []byte) (NameRecordHeader, error) { | ||
if len(data) < 96 { | ||
return NameRecordHeader{}, fmt.Errorf("data length should bigger than 96") | ||
} | ||
return NameRecordHeader{ | ||
ParentName: common.PublicKeyFromBytes(data[:32]), | ||
Owner: common.PublicKeyFromBytes(data[32:64]), | ||
Class: common.PublicKeyFromBytes(data[64:96]), | ||
Data: data[96:], | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package nsprog | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/portto/solana-go-sdk/common" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestNameRecordHeaderFromData(t *testing.T) { | ||
type args struct { | ||
data []byte | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want NameRecordHeader | ||
err error | ||
}{ | ||
{ | ||
args: args{ | ||
data: []byte{0x3d, 0x53, 0xc2, 0x4b}, | ||
}, | ||
want: NameRecordHeader{}, | ||
err: fmt.Errorf("data length should bigger than 96"), | ||
}, | ||
{ | ||
args: args{ | ||
data: []byte{0x3d, 0x53, 0xc2, 0x4b, 0x38, 0x36, 0xe, 0xd3, 0x81, 0x3a, 0x23, 0xdf, 0xb2, 0xdf, 0xd8, 0x20, 0xab, 0x58, 0x21, 0xcb, 0x79, 0x29, 0xa3, 0x8d, 0x2e, 0xaa, 0xb2, 0x52, 0xe8, 0x38, 0x25, 0x95, 0x58, 0x7f, 0x6a, 0x3d, 0xab, 0x65, 0xe7, 0x3e, 0x12, 0xde, 0x67, 0xbc, 0x31, 0x73, 0x2d, 0xa0, 0x4e, 0xea, 0xfb, 0x12, 0x83, 0xdd, 0x21, 0x10, 0x82, 0x5c, 0xcb, 0x1e, 0xdf, 0x79, 0xa2, 0xb0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6a, 0x61, 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x37, 0x37, 0x32, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x73, 0x61, 0x6c, 0x65, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, | ||
}, | ||
want: NameRecordHeader{ | ||
ParentName: common.PublicKeyFromString("58PwtjSDuFHuUkYjH9BYnnQKHfwo9reZhC2zMJv9JPkx"), | ||
Class: common.PublicKey{}, | ||
Owner: common.PublicKeyFromString("6xTZhtNA8aaipc2hHFP616gFvDcvWmYMGsDFHwrsF3m1"), | ||
Data: []byte{0x52, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6a, 0x61, 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x37, 0x37, 0x32, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x73, 0x61, 0x6c, 0x65, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, | ||
}, | ||
err: nil, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
got, err := NameRecordHeaderFromData(tt.args.data) | ||
assert.Equal(t, tt.err, err) | ||
assert.Equal(t, tt.want, got) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package nsprog | ||
|
||
import ( | ||
"crypto/sha256" | ||
|
||
"github.com/portto/solana-go-sdk/common" | ||
) | ||
|
||
var TwitterVerificationAuthority = common.PublicKeyFromString("FvPH7PrVrLGKPfqaf3xJodFTjZriqrAXXLTVWEorTFBi") | ||
var TwitterRootParentRegisteryKey = common.PublicKeyFromString("4YcexoW3r78zz16J2aqmukBLRwGq6rAvWzJpkYAXqebv") | ||
var SolTldAuthority = common.PublicKeyFromString("58PwtjSDuFHuUkYjH9BYnnQKHfwo9reZhC2zMJv9JPkx") | ||
|
||
const HashPrefix = "SPL Name Service" | ||
|
||
// GetHashName ... | ||
func GetHashName(name string) []byte { | ||
h := sha256.Sum256([]byte(HashPrefix + name)) | ||
return h[:] | ||
} | ||
|
||
// GetNameAccountKey return the pubkey correspond to name | ||
func GetNameAccountKey(hashName []byte, nameClass, nameParent common.PublicKey) common.PublicKey { | ||
seed := [][]byte{ | ||
hashName, | ||
nameClass.Bytes(), | ||
nameParent.Bytes(), | ||
} | ||
pubkey, _, _ := common.FindProgramAddress(seed, common.SPLNameServiceProgramID) | ||
return pubkey | ||
} | ||
|
||
// GetTwitterRegistryKey return the pubkey corespond to twitter handle | ||
func GetTwitterRegistryKey(twitterHandle string) common.PublicKey { | ||
return GetNameAccountKey( | ||
GetHashName(twitterHandle), | ||
common.PublicKey{}, | ||
TwitterRootParentRegisteryKey, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package nsprog | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/portto/solana-go-sdk/common" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestGetTwitterRegistryKey(t *testing.T) { | ||
type args struct { | ||
twitterHandle string | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want common.PublicKey | ||
}{ | ||
{ | ||
args: args{ | ||
twitterHandle: "gghost07114721", | ||
}, | ||
want: common.PublicKeyFromString("5r2pKbCFibGZp18u51tcvzQpsNsA98TyCF1UbDmbSUk5"), | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
assert.Equal(t, tt.want, GetTwitterRegistryKey(tt.args.twitterHandle)) | ||
}) | ||
} | ||
} | ||
|
||
func TestGetHashName(t *testing.T) { | ||
type args struct { | ||
name string | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want []byte | ||
}{ | ||
{ | ||
args: args{ | ||
name: "blocto", | ||
}, | ||
want: []byte{0x62, 0x94, 0x3a, 0xc2, 0x9e, 0x7b, 0x9d, 0x4e, 0x38, 0x53, 0xb2, 0x84, 0xdd, 0x7f, 0x1, 0x66, 0xeb, 0x5f, 0x0, 0xe3, 0x1f, 0x25, 0x53, 0x51, 0x83, 0x61, 0x38, 0x33, 0xcd, 0xc5, 0xf9, 0x3}, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := GetHashName(tt.args.name); !reflect.DeepEqual(got, tt.want) { | ||
t.Errorf("GetHashName() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestGetNameAccountKey(t *testing.T) { | ||
type args struct { | ||
hashName []byte | ||
nameClass common.PublicKey | ||
nameParent common.PublicKey | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want common.PublicKey | ||
}{ | ||
{ | ||
name: "domain: blocto.sol", | ||
args: args{ | ||
hashName: GetHashName("blocto"), | ||
nameClass: common.PublicKey{}, | ||
nameParent: SolTldAuthority, | ||
}, | ||
want: common.PublicKeyFromString("6yAP2rFW7wQiqVmySE4DTfQSWmp6fR1geGyWx6SQMAhS"), | ||
}, | ||
{ | ||
name: "domain yihau.blocto.sol", | ||
args: args{ | ||
hashName: GetHashName("\x00yihau"), | ||
nameClass: common.PublicKey{}, | ||
nameParent: GetNameAccountKey(GetHashName("blocto"), common.PublicKey{}, SolTldAuthority), | ||
}, | ||
want: common.PublicKeyFromString("5Cjg2Xah4Cc24yM7zsfbyBuXKZ6Wm9ZJqHa5n47vnvNz"), | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := GetNameAccountKey(tt.args.hashName, tt.args.nameClass, tt.args.nameParent); !reflect.DeepEqual(got, tt.want) { | ||
t.Errorf("GetNameAccountKey() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |