|
| 1 | +package examples |
| 2 | + |
| 3 | +import ( |
| 4 | + "fmt" |
| 5 | + "math/rand/v2" |
| 6 | + |
| 7 | + "github.com/availproject/avail-go-sdk/metadata" |
| 8 | + "github.com/availproject/avail-go-sdk/metadata/pallets" |
| 9 | + baPallet "github.com/availproject/avail-go-sdk/metadata/pallets/balances" |
| 10 | + daPallet "github.com/availproject/avail-go-sdk/metadata/pallets/data_availability" |
| 11 | + pxPallet "github.com/availproject/avail-go-sdk/metadata/pallets/proxy" |
| 12 | + "github.com/availproject/avail-go-sdk/primitives" |
| 13 | + SDK "github.com/availproject/avail-go-sdk/sdk" |
| 14 | +) |
| 15 | + |
| 16 | +// Understanding Proxy Account: |
| 17 | +// |
| 18 | +// From a simplified perspective, proxy account acts as a family member that we trust. |
| 19 | +// |
| 20 | +// If we designate the name "Child" to our main account, then te proxy account will |
| 21 | +// be designated with the name "Parent". The "Parent" can do anything in the name of "Child" |
| 22 | +// while the "Child" cannot do anything in the name of "Parent". |
| 23 | +// |
| 24 | +// This means that the "Parent", if he wants, can take all the funds from "Child" if he thinks |
| 25 | +// that the "Child" has misbehaved, or the "Parent" can force the "Child" to work as a validator |
| 26 | +// in order to gather some funds. |
| 27 | +// |
| 28 | +// The "Child" can, if needed, break this bond and force the "Parent" to become childless. |
| 29 | +// The "Parent" can, if needed, break this bond and force the "Child" to become fatherless (an orphan). |
| 30 | +// |
| 31 | +// There are different types of Proxy account with different levels of authority. |
| 32 | +// |
| 33 | +// Pure Proxy accounts work in the opposite direction. If we designate the name "Parent" to our main account, |
| 34 | +// then the proxy account will be designated with the name "Child". The "Child" cannot do anything on it's own |
| 35 | +// and the "Parent" has full control over it. The "Parent" can forget that he even had the "Child" in the first |
| 36 | +// place thus forcing the "Child" to become an orphan that no will ever see again. |
| 37 | + |
| 38 | +func RunProxy() { |
| 39 | + RunNormalProxy() |
| 40 | + RunPureProxy() |
| 41 | + |
| 42 | + fmt.Println("RunProxy finished correctly.") |
| 43 | +} |
| 44 | + |
| 45 | +func RunNormalProxy() { |
| 46 | + sdk, err := SDK.NewSDK(SDK.LocalEndpoint) |
| 47 | + PanicOnError(err) |
| 48 | + |
| 49 | + // Bob is the "Parent" account |
| 50 | + parent := SDK.Account.Bob() |
| 51 | + parentMulti := metadata.NewAccountIdFromKeyPair(parent).ToMultiAddress() |
| 52 | + // Ferdie is the "Child" account |
| 53 | + child := SDK.Account.Ferdie() |
| 54 | + |
| 55 | + // Let's create a proxy and make Bob the "Parent" and Ferdie the "Child" |
| 56 | + proxyType := metadata.ProxyType{VariantIndex: 0} // Any Proxy |
| 57 | + tx := sdk.Tx.Proxy.AddProxy(parentMulti, proxyType, 0) |
| 58 | + res, err := tx.ExecuteAndWatchInclusion(child, SDK.NewTransactionOptions()) |
| 59 | + PanicOnError(err) |
| 60 | + |
| 61 | + AssertTrue(res.IsSuccessful().Unwrap(), "Transaction has to succeed") |
| 62 | + AssertTrue(res.Events.IsSome(), "Events need to be decodable") |
| 63 | + |
| 64 | + // Finding the Proxy Added Event |
| 65 | + // In production you would use `EventFindFirstChecked`` instead of `EventFindFirst`. |
| 66 | + event := SDK.EventFindFirst(res.Events.Unwrap(), pxPallet.EventProxyAdded{}).UnsafeUnwrap() |
| 67 | + fmt.Println(fmt.Sprintf(`Delegatee: %v, Delegator %v, ProxyTpe %v, Delay: %v`, event.Delegatee.ToHuman(), event.Delegator.ToHuman(), event.ProxyTpe.ToHuman(), event.Delay)) |
| 68 | + |
| 69 | + // The "Child" account misbehaved so "Parent" decided to take his allowance. 1.0 Avail will be "taken" |
| 70 | + realAddress := metadata.NewAccountIdFromKeyPair(child).ToMultiAddress() |
| 71 | + call := pallets.ToCall(baPallet.CallTransferKeepAlive{Dest: parentMulti, Value: SDK.OneAvail()}) |
| 72 | + |
| 73 | + tx = sdk.Tx.Proxy.Proxy(realAddress, primitives.NewNone[metadata.ProxyType](), call) |
| 74 | + res, err = tx.ExecuteAndWatchInclusion(parent, SDK.NewTransactionOptions()) |
| 75 | + PanicOnError(err) |
| 76 | + AssertTrue(res.IsSuccessful().Unwrap(), "Transaction has to succeed") |
| 77 | + |
| 78 | + // Checking for EventProxyExecuted event. |
| 79 | + // In production you would use `EventFindFirstChecked`` instead of `EventFindFirst`. |
| 80 | + event2 := SDK.EventFindFirst(res.Events.Unwrap(), pxPallet.EventProxyExecuted{}).UnsafeUnwrap() |
| 81 | + AssertEq(event2.Result.VariantIndex, 0, "Event must OK") |
| 82 | + fmt.Println(fmt.Sprintf(`Dispatch Result: %v`, event2.Result.ToString())) |
| 83 | + |
| 84 | + // "Child" is angry at "Parent" so he decides to cut all the dies with him |
| 85 | + tx = sdk.Tx.Proxy.RemoveProxy(parentMulti, proxyType, 0) |
| 86 | + res, err = tx.ExecuteAndWatchInclusion(child, SDK.NewTransactionOptions()) |
| 87 | + PanicOnError(err) |
| 88 | + |
| 89 | + AssertTrue(res.IsSuccessful().Unwrap(), "Transaction has to succeed") |
| 90 | + AssertTrue(res.Events.IsSome(), "Events need to be decodable") |
| 91 | + |
| 92 | + // Checking for EventProxyExecuted event. |
| 93 | + // In production you would use `EventFindFirstChecked`` instead of `EventFindFirst`. |
| 94 | + event3 := SDK.EventFindFirst(res.Events.Unwrap(), pxPallet.EventProxyRemoved{}).UnsafeUnwrap() |
| 95 | + AssertEq(event2.Result.VariantIndex, 0, "Event must OK") |
| 96 | + fmt.Println(fmt.Sprintf(`Delegatee: %v, Delegator %v, ProxyTpe %v, Delay: %v`, event3.Delegatee.ToHuman(), event3.Delegator.ToHuman(), event3.ProxyTpe.ToHuman(), event3.Delay)) |
| 97 | + |
| 98 | + fmt.Println("RunNormalProxy finished correctly.") |
| 99 | +} |
| 100 | + |
| 101 | +func RunPureProxy() { |
| 102 | + sdk, err := SDK.NewSDK(SDK.LocalEndpoint) |
| 103 | + PanicOnError(err) |
| 104 | + |
| 105 | + // Bob is the "Parent" account |
| 106 | + parent := SDK.Account.Bob() |
| 107 | + |
| 108 | + // Creating Pure Proxy |
| 109 | + proxyType := metadata.ProxyType{VariantIndex: 0} // Any Proxy |
| 110 | + index := uint16(0) |
| 111 | + tx := sdk.Tx.Proxy.CreatePure(proxyType, 0, index) |
| 112 | + res, err := tx.ExecuteAndWatchInclusion(parent, SDK.NewTransactionOptions()) |
| 113 | + PanicOnError(err) |
| 114 | + |
| 115 | + AssertTrue(res.IsSuccessful().Unwrap(), "Transaction has to succeed") |
| 116 | + AssertTrue(res.Events.IsSome(), "Events need to be decodable") |
| 117 | + |
| 118 | + // Finding the Pure Created Event |
| 119 | + // In production you would use `EventFindFirstChecked`` instead of `EventFindFirst`. |
| 120 | + event := SDK.EventFindFirst(res.Events.Unwrap(), pxPallet.EventPureCreated{}).UnsafeUnwrap() |
| 121 | + fmt.Println(fmt.Sprintf(`Pure: %v, Who %v, ProxyType %v, Index: %v`, event.Pure.ToHuman(), event.Who.ToHuman(), event.ProxyTpe.ToHuman(), event.DisambiguationIndex)) |
| 122 | + child := event.Pure |
| 123 | + |
| 124 | + // Forcing "Child" to create an application key |
| 125 | + key := fmt.Sprintf("MyKey%v", rand.Uint32()) |
| 126 | + call := pallets.ToCall(daPallet.CallCreateApplicationKey{Key: []byte(key)}) |
| 127 | + tx = sdk.Tx.Proxy.Proxy(child.ToMultiAddress(), primitives.NewNone[metadata.ProxyType](), call) |
| 128 | + res, err = tx.ExecuteAndWatchInclusion(parent, SDK.NewTransactionOptions()) |
| 129 | + PanicOnError(err) |
| 130 | + AssertTrue(res.IsSuccessful().Unwrap(), "Transaction has to succeed") |
| 131 | + |
| 132 | + // Finding the Proxy Executed Event |
| 133 | + // In production you would use `EventFindFirstChecked`` instead of `EventFindFirst`. |
| 134 | + event2 := SDK.EventFindFirst(res.Events.Unwrap(), pxPallet.EventProxyExecuted{}).UnsafeUnwrap() |
| 135 | + AssertEq(event2.Result.VariantIndex, 0, "Event must OK") |
| 136 | + fmt.Println(fmt.Sprintf(`Dispatch Result: %v`, event2.Result.ToString())) |
| 137 | + |
| 138 | + fmt.Println("RunPureProxy finished correctly.") |
| 139 | +} |
0 commit comments