Skip to content

Commit

Permalink
Add support for maps w/ ecids.
Browse files Browse the repository at this point in the history
  • Loading branch information
q-uint committed May 14, 2024
1 parent 51e4c9b commit 94fe9b1
Show file tree
Hide file tree
Showing 20 changed files with 688 additions and 655 deletions.
28 changes: 21 additions & 7 deletions agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,37 @@ func effectiveCanisterID(canisterID principal.Principal, args []any) principal.P
}

v := reflect.ValueOf(args[0])
if v.Kind() == reflect.Struct {
switch v.Kind() {
case reflect.Map:
if ecid, ok := args[0].(map[string]any)["canister_id"]; ok {
switch ecidp := ecid.(type) {
case principal.Principal:
return ecidp
default:
// If the field is not a principal, return the original canisterId.
return canisterID
}
}
return canisterID
case reflect.Struct:
t := v.Type()
// Get the field with the ic tag "canister_id".
for idx := range t.NumField() {
if tag := t.Field(idx).Tag.Get("ic"); tag == "canister_id" {
ecid := v.Field(idx).Interface()
switch ecid := ecid.(type) {
switch ecidp := ecid.(type) {
case principal.Principal:
return ecid
return ecidp
default:
// If the field is not a principal, return the original canisterId.
return canisterID
}
}
}
return canisterID
default:
return canisterID
}
return canisterID
}

func newNonce() ([]byte, error) {
Expand Down Expand Up @@ -233,7 +247,7 @@ func (a Agent) GetCanisterControllers(canisterID principal.Principal) ([]princip
// GetCanisterInfo returns the raw certificate for the given canister based on the given sub-path.
func (a Agent) GetCanisterInfo(canisterID principal.Principal, subPath string) ([]byte, error) {
path := []hashtree.Label{hashtree.Label("canister"), canisterID.Raw, hashtree.Label(subPath)}
node, err := a.ReadState(canisterID, [][]hashtree.Label{path})
node, err := a.ReadStateCertificate(canisterID, [][]hashtree.Label{path})
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -290,8 +304,8 @@ func (a Agent) Query(canisterID principal.Principal, methodName string, args []a
return query.Query(values...)
}

// ReadState reads the state of the given canister at the given path.
func (a Agent) ReadState(canisterID principal.Principal, path [][]hashtree.Label) (hashtree.Node, error) {
// ReadStateCertificate reads the certificate state of the given canister at the given path.
func (a Agent) ReadStateCertificate(canisterID principal.Principal, path [][]hashtree.Label) (hashtree.Node, error) {
c, err := a.readStateCertificate(canisterID, path)
if err != nil {
return nil, err
Expand Down
17 changes: 9 additions & 8 deletions agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ package agent_test
import (
"encoding/json"
"fmt"
"testing"

"github.com/aviate-labs/agent-go"
"github.com/aviate-labs/agent-go/candid/idl"
"github.com/aviate-labs/agent-go/certification/hashtree"
"github.com/aviate-labs/agent-go/ic"
mgmt "github.com/aviate-labs/agent-go/ic/ic"
ic0 "github.com/aviate-labs/agent-go/ic/ic"
"github.com/aviate-labs/agent-go/ic/icpledger"
"github.com/aviate-labs/agent-go/identity"
"github.com/aviate-labs/agent-go/principal"
"testing"
)

var _ = new(testLogger)
Expand Down Expand Up @@ -104,7 +105,7 @@ func TestAgent_Call(t *testing.T) {
if err != nil {
t.Fatal(err)
}
n, err := a.ReadState(ic.REGISTRY_PRINCIPAL, [][]hashtree.Label{{hashtree.Label("subnet")}})
n, err := a.ReadStateCertificate(ic.REGISTRY_PRINCIPAL, [][]hashtree.Label{{hashtree.Label("subnet")}})
if err != nil {
t.Fatal(err)
}
Expand All @@ -117,13 +118,13 @@ func TestAgent_Call(t *testing.T) {
}

func TestAgent_Call_bitcoinGetBalanceQuery(t *testing.T) {
a, err := mgmt.NewAgent(ic.MANAGEMENT_CANISTER_PRINCIPAL, agent.DefaultConfig)
a, err := ic0.NewAgent(ic.MANAGEMENT_CANISTER_PRINCIPAL, agent.DefaultConfig)
if err != nil {
t.Fatal(err)
}
r, err := a.BitcoinGetBalanceQuery(mgmt.BitcoinGetBalanceQueryArgs{
r, err := a.BitcoinGetBalanceQuery(ic0.BitcoinGetBalanceQueryArgs{
Address: "bc1qruu3xmfrt4nzkxax3lpxfmjega87jr3vqcwjn9",
Network: mgmt.BitcoinNetwork{
Network: ic0.BitcoinNetwork{
Mainnet: new(idl.Null),
},
})
Expand All @@ -136,11 +137,11 @@ func TestAgent_Call_bitcoinGetBalanceQuery(t *testing.T) {
}

func TestAgent_Call_provisionalTopUpCanister(t *testing.T) {
a, err := mgmt.NewAgent(ic.MANAGEMENT_CANISTER_PRINCIPAL, agent.DefaultConfig)
a, err := ic0.NewAgent(ic.MANAGEMENT_CANISTER_PRINCIPAL, agent.DefaultConfig)
if err != nil {
t.Fatal(err)
}
if err := a.ProvisionalTopUpCanister(mgmt.ProvisionalTopUpCanisterArgs{
if err := a.ProvisionalTopUpCanister(ic0.ProvisionalTopUpCanisterArgs{
CanisterId: ic.LEDGER_PRINCIPAL,
}); err == nil {
t.Fatal()
Expand Down
12 changes: 6 additions & 6 deletions gen/templates/agent.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ type {{ .Name }} {{ if .Eq }}= {{end}}{{ .Type }}

// {{ .AgentName }}Agent is a client for the "{{ .CanisterName }}" canister.
type {{ .AgentName }}Agent struct {
a *agent.Agent
canisterId principal.Principal
*agent.Agent
CanisterId principal.Principal
}

// New{{ .AgentName }}Agent creates a new agent for the "{{ .CanisterName }}" canister.
Expand All @@ -26,8 +26,8 @@ func New{{ .AgentName }}Agent(canisterId principal.Principal, config agent.Confi
return nil, err
}
return &{{ .AgentName }}Agent{
a: a,
canisterId: canisterId,
Agent: a,
CanisterId: canisterId,
}, nil
}
{{- range .Methods }}
Expand All @@ -37,8 +37,8 @@ func (a {{ $.AgentName }}Agent) {{ .Name }}({{ range $i, $e := .ArgumentTypes }}
{{ range $i, $e := .ReturnTypes -}}
var r{{ $i }} {{ $e }}
{{ end -}}
if err := a.a.{{ .Type }}(
a.canisterId,
if err := a.Agent.{{ .Type }}(
a.CanisterId,
"{{ .RawName }}",
[]any{{ "{" }}{{ range $i, $e := .ArgumentTypes }}{{ if $i }}, {{ end }}{{ $e.Name }}{{ end }}{{ "}" }},
[]any{{ "{" }}{{ range $i, $e := .ReturnTypes }}{{ if $i }}, {{ end }}&r{{ $i }}{{ end }}{{ "}"}},
Expand Down
16 changes: 8 additions & 8 deletions gen/templates/agent_indirect.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ type {{ .Name }} {{ if .Eq }}= {{end}}{{ .Type }}

// {{ .AgentName }}Agent is a client for the "{{ .CanisterName }}" canister.
type {{ .AgentName }}Agent struct {
a *agent.Agent
canisterId principal.Principal
*agent.Agent
CanisterId principal.Principal
}

// New{{ .AgentName }}Agent creates a new agent for the "{{ .CanisterName }}" canister.
Expand All @@ -26,8 +26,8 @@ func New{{ .AgentName }}Agent(canisterId principal.Principal, config agent.Confi
return nil, err
}
return &{{ .AgentName }}Agent{
a: a,
canisterId: canisterId,
Agent: a,
CanisterId: canisterId,
}, nil
}
{{- range .Methods }}
Expand All @@ -37,8 +37,8 @@ func (a {{ $.AgentName }}Agent) {{ .Name }}({{ range $i, $e := .ArgumentTypes }}
{{ range $i, $e := .ReturnTypes -}}
var r{{ $i }} {{ $e }}
{{ end -}}
if err := a.a.{{ .Type }}(
a.canisterId,
if err := a.Agent.{{ .Type }}(
a.CanisterId,
"{{ .RawName }}",
[]any{{ "{" }}{{ range $i, $e := .ArgumentTypes }}{{ if $i }}, {{ end }}{{ $e.Name }}{{ end }}{{ "}" }},
[]any{{ "{" }}{{ range $i, $e := .ReturnTypes }}{{ if $i }}, {{ end }}&r{{ $i }}{{ end }}{{ "}"}},
Expand All @@ -50,8 +50,8 @@ func (a {{ $.AgentName }}Agent) {{ .Name }}({{ range $i, $e := .ArgumentTypes }}

// {{ .Name }}{{ .Type }} creates an indirect representation of the "{{ .RawName }}" method on the "{{ $.CanisterName }}" canister.
func (a {{ $.AgentName }}Agent) {{ .Name }}{{ .Type }}({{ range $i, $e := .ArgumentTypes }}{{ if $i }}, {{ end }}{{ $e.Name }} {{ $e.Type }}{{ end }}) (*agent.{{ .Type }},error) {
return a.a.Create{{ .Type }}(
a.canisterId,
return a.Agent.Create{{ .Type }}(
a.CanisterId,
"{{ .RawName }}",{{ range $i, $e := .ArgumentTypes }}
{{ $e.Name }},{{ end }}
)
Expand Down

0 comments on commit 94fe9b1

Please sign in to comment.