Skip to content

Commit b3a4c80

Browse files
anzomanclaude
andcommitted
cmd/rofl: Consolidate offer helpers and show allowed creators
Moves `ShowOfferSummary` from `cmd/rofl/provider` to `cmd/rofl/common` next to the offer filtering, inlines `PublicOffers` into `FilterOffers` and renames the file to `provider.go`. Offer summaries now also list the accounts allowed to rent a machine from the offer, read from the on-chain metadata via the new `OfferAllowedCreators` helper. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SnBPUK6S6UMyxRJ4nhUVH6
1 parent a2c32dd commit b3a4c80

7 files changed

Lines changed: 147 additions & 99 deletions

File tree

‎build/rofl/provider/manifest.go‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,25 @@ func joinMetadataList(items []string) string {
351351
return strings.Join(slices.Compact(items), ",")
352352
}
353353

354+
// splitMetadataList deserializes a comma-separated metadata value into the list of its items.
355+
func splitMetadataList(value string) []string {
356+
items := strings.Split(value, ",")
357+
result := make([]string, 0, len(items))
358+
for _, item := range items {
359+
if item = strings.TrimSpace(item); item == "" {
360+
continue
361+
}
362+
result = append(result, item)
363+
}
364+
return result
365+
}
366+
367+
// OfferAllowedCreators returns the accounts allowed to rent machines from the given on-chain
368+
// offer. When the returned list is empty, anyone can rent a machine.
369+
func OfferAllowedCreators(offer *roflmarket.Offer) []string {
370+
return splitMetadataList(offer.Metadata[SchedulerMetadataOfferAllowedCreatorsKey])
371+
}
372+
354373
// IsOfferPrivate returns true iff the given on-chain offer is marked as private and should thus be
355374
// hidden from public offer listings.
356375
func IsOfferPrivate(offer *roflmarket.Offer) bool {

‎build/rofl/provider/manifest_test.go‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,25 @@ func TestIsOfferPrivate(t *testing.T) {
181181
Metadata: map[string]string{SchedulerMetadataOfferPrivateKey: SchedulerMetadataValueTrue},
182182
}))
183183
}
184+
185+
func TestOfferAllowedCreators(t *testing.T) {
186+
require := require.New(t)
187+
188+
alice, bob := testAddresses["alice"], testAddresses["bob"]
189+
190+
require.Empty(OfferAllowedCreators(&roflmarket.Offer{}))
191+
require.Empty(OfferAllowedCreators(&roflmarket.Offer{
192+
Metadata: map[string]string{SchedulerMetadataOfferAllowedCreatorsKey: ""},
193+
}))
194+
require.Equal([]string{alice, bob}, OfferAllowedCreators(&roflmarket.Offer{
195+
Metadata: map[string]string{
196+
SchedulerMetadataOfferAllowedCreatorsKey: alice + "," + bob,
197+
},
198+
}))
199+
// Stray whitespace and empty items are ignored.
200+
require.Equal([]string{alice}, OfferAllowedCreators(&roflmarket.Offer{
201+
Metadata: map[string]string{
202+
SchedulerMetadataOfferAllowedCreatorsKey: " " + alice + " ,, ",
203+
},
204+
}))
205+
}

‎cmd/rofl/common/offer.go‎

Lines changed: 0 additions & 28 deletions
This file was deleted.

‎cmd/rofl/common/provider.go‎

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package common
2+
3+
import (
4+
"fmt"
5+
"sort"
6+
"strings"
7+
8+
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/helpers"
9+
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/roflmarket"
10+
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/types"
11+
12+
"github.com/oasisprotocol/cli/build/rofl/provider"
13+
"github.com/oasisprotocol/cli/cmd/common"
14+
)
15+
16+
// FilterOffers removes the offers marked as private from the given listing, unless the user
17+
// explicitly asked for them via --all.
18+
func FilterOffers(offers []*roflmarket.Offer) []*roflmarket.Offer {
19+
if ShowPrivateOffers {
20+
return offers
21+
}
22+
23+
public := make([]*roflmarket.Offer, 0, len(offers))
24+
for _, offer := range offers {
25+
if provider.IsOfferPrivate(offer) {
26+
continue
27+
}
28+
public = append(public, offer)
29+
}
30+
return public
31+
}
32+
33+
// ShowOfferSummary outputs a summary of a single offer.
34+
func ShowOfferSummary(npa *common.NPASelection, offer *roflmarket.Offer) {
35+
// Extract offer name from metadata if available.
36+
name, ok := offer.Metadata[provider.SchedulerMetadataOfferKey]
37+
if !ok {
38+
name = "<unnamed>"
39+
}
40+
41+
// Determine TEE type.
42+
tee := FormatTeeType(offer.Resources.TEE)
43+
44+
// Format GPU info if present.
45+
var gpu string
46+
if offer.Resources.GPU != nil {
47+
gpu = fmt.Sprintf(" | GPU: %d", offer.Resources.GPU.Count)
48+
if offer.Resources.GPU.Model != "" {
49+
gpu += fmt.Sprintf(" (%s)", offer.Resources.GPU.Model)
50+
}
51+
}
52+
53+
var private string
54+
if provider.IsOfferPrivate(offer) {
55+
private = " (private)"
56+
}
57+
58+
fmt.Printf(" - %s [%s]%s\n", name, offer.ID, private)
59+
fmt.Printf(" TEE: %s | Memory: %d MiB | vCPUs: %d | Storage: %.2f GiB%s\n",
60+
tee,
61+
offer.Resources.Memory,
62+
offer.Resources.CPUCount,
63+
float64(offer.Resources.Storage)/1024.,
64+
gpu,
65+
)
66+
fmt.Printf(" Capacity: %d\n", offer.Capacity)
67+
68+
// Note and Description from metadata.
69+
if note, ok := offer.Metadata[provider.NoteMetadataKey]; ok {
70+
fmt.Printf(" Note: %s\n", note)
71+
}
72+
if desc, ok := offer.Metadata[provider.DescriptionMetadataKey]; ok {
73+
fmt.Printf(" Description:\n %s\n", strings.ReplaceAll(desc, "\n", "\n "))
74+
}
75+
76+
// Accounts allowed to rent machines, when the offer is restricted.
77+
if creators := provider.OfferAllowedCreators(offer); len(creators) > 0 {
78+
prettyCreators := make([]string, 0, len(creators))
79+
for _, creator := range creators {
80+
prettyCreators = append(prettyCreators, common.PrettyAddress(creator))
81+
}
82+
fmt.Printf(" Allowed creators: %s\n", strings.Join(prettyCreators, ", "))
83+
}
84+
85+
// Payment info.
86+
switch {
87+
case offer.Payment.Native != nil:
88+
if len(offer.Payment.Native.Terms) > 0 {
89+
var terms []string //nolint: prealloc
90+
for term, amount := range offer.Payment.Native.Terms {
91+
bu := types.NewBaseUnits(amount, offer.Payment.Native.Denomination)
92+
formattedAmount := helpers.FormatParaTimeDenomination(npa.ParaTime, bu)
93+
terms = append(terms, fmt.Sprintf("%s: %s", FormatTermAdjectival(term), formattedAmount))
94+
}
95+
sort.Strings(terms)
96+
fmt.Printf(" Payment: %s\n", strings.Join(terms, ", "))
97+
}
98+
case offer.Payment.EvmContract != nil:
99+
fmt.Printf(" Payment: EVM Contract (0x%x)\n", offer.Payment.EvmContract.Address[:])
100+
}
101+
}

‎cmd/rofl/deploy.go‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import (
3232
"github.com/oasisprotocol/cli/cmd/common"
3333
roflCmdBuild "github.com/oasisprotocol/cli/cmd/rofl/build"
3434
roflCommon "github.com/oasisprotocol/cli/cmd/rofl/common"
35-
roflProvider "github.com/oasisprotocol/cli/cmd/rofl/provider"
3635
cliConfig "github.com/oasisprotocol/cli/config"
3736
)
3837

@@ -141,7 +140,7 @@ var (
141140
fmt.Println()
142141
fmt.Printf("Offers available from the selected provider:\n")
143142
for _, offer := range roflCommon.FilterOffers(offers) {
144-
roflProvider.ShowOfferSummary(npa, offer)
143+
roflCommon.ShowOfferSummary(npa, offer)
145144
}
146145
fmt.Println()
147146
return
@@ -210,14 +209,14 @@ var (
210209
fmt.Println()
211210
fmt.Printf("Offers available from the selected provider:\n")
212211
for _, of := range roflCommon.FilterOffers(offers) {
213-
roflProvider.ShowOfferSummary(npa, of)
212+
roflCommon.ShowOfferSummary(npa, of)
214213
}
215214
fmt.Println()
216215
return nil, nil, fmt.Errorf("offer '%s' not found for provider '%s'", machine.Offer, providerAddr)
217216
}
218217

219218
fmt.Printf("Taking offer:\n")
220-
roflProvider.ShowOfferSummary(npa, offer)
219+
roflCommon.ShowOfferSummary(npa, offer)
221220

222221
term := detectTerm(offer)
223222
if roflCommon.TermCount < 1 {

‎cmd/rofl/provider/list.go‎

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,13 @@ import (
55
"encoding/json"
66
"fmt"
77
"sort"
8-
"strings"
98

109
"github.com/spf13/cobra"
1110

1211
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/client"
1312
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/connection"
14-
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/helpers"
1513
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/roflmarket"
16-
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/types"
1714

18-
"github.com/oasisprotocol/cli/build/rofl/provider"
1915
"github.com/oasisprotocol/cli/cmd/common"
2016
roflCommon "github.com/oasisprotocol/cli/cmd/rofl/common"
2117
cliConfig "github.com/oasisprotocol/cli/config"
@@ -160,72 +156,11 @@ func showProviderOffersExpanded(ctx context.Context, npa *common.NPASelection, c
160156

161157
fmt.Printf("Provider %s (%d offers):\n", prettyAddr, len(offers))
162158
for _, offer := range offers {
163-
ShowOfferSummary(npa, offer)
159+
roflCommon.ShowOfferSummary(npa, offer)
164160
}
165161
fmt.Println()
166162
}
167163

168-
// ShowOfferSummary outputs a summary of a single offer.
169-
func ShowOfferSummary(npa *common.NPASelection, offer *roflmarket.Offer) {
170-
// Extract offer name from metadata if available.
171-
name, ok := offer.Metadata[provider.SchedulerMetadataOfferKey]
172-
if !ok {
173-
name = "<unnamed>"
174-
}
175-
176-
// Determine TEE type.
177-
tee := roflCommon.FormatTeeType(offer.Resources.TEE)
178-
179-
// Format GPU info if present.
180-
var gpu string
181-
if offer.Resources.GPU != nil {
182-
gpu = fmt.Sprintf(" | GPU: %d", offer.Resources.GPU.Count)
183-
if offer.Resources.GPU.Model != "" {
184-
gpu += fmt.Sprintf(" (%s)", offer.Resources.GPU.Model)
185-
}
186-
}
187-
188-
var private string
189-
if provider.IsOfferPrivate(offer) {
190-
private = " (private)"
191-
}
192-
193-
fmt.Printf(" - %s [%s]%s\n", name, offer.ID, private)
194-
fmt.Printf(" TEE: %s | Memory: %d MiB | vCPUs: %d | Storage: %.2f GiB%s\n",
195-
tee,
196-
offer.Resources.Memory,
197-
offer.Resources.CPUCount,
198-
float64(offer.Resources.Storage)/1024.,
199-
gpu,
200-
)
201-
fmt.Printf(" Capacity: %d\n", offer.Capacity)
202-
203-
// Note and Description from metadata.
204-
if note, ok := offer.Metadata[provider.NoteMetadataKey]; ok {
205-
fmt.Printf(" Note: %s\n", note)
206-
}
207-
if desc, ok := offer.Metadata[provider.DescriptionMetadataKey]; ok {
208-
fmt.Printf(" Description:\n %s\n", strings.ReplaceAll(desc, "\n", "\n "))
209-
}
210-
211-
// Payment info.
212-
switch {
213-
case offer.Payment.Native != nil:
214-
if len(offer.Payment.Native.Terms) > 0 {
215-
var terms []string //nolint: prealloc
216-
for term, amount := range offer.Payment.Native.Terms {
217-
bu := types.NewBaseUnits(amount, offer.Payment.Native.Denomination)
218-
formattedAmount := helpers.FormatParaTimeDenomination(npa.ParaTime, bu)
219-
terms = append(terms, fmt.Sprintf("%s: %s", roflCommon.FormatTermAdjectival(term), formattedAmount))
220-
}
221-
sort.Strings(terms)
222-
fmt.Printf(" Payment: %s\n", strings.Join(terms, ", "))
223-
}
224-
case offer.Payment.EvmContract != nil:
225-
fmt.Printf(" Payment: EVM Contract (0x%x)\n", offer.Payment.EvmContract.Address[:])
226-
}
227-
}
228-
229164
func init() {
230165
listCmd.Flags().AddFlagSet(roflCommon.ShowOffersFlag)
231166
listCmd.Flags().AddFlagSet(roflCommon.ShowPrivateOffersFlag)

‎cmd/rofl/provider/show.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ func outputProviderText(npa *common.NPASelection, provider *roflmarket.Provider,
151151
})
152152

153153
for _, offer := range offers {
154-
ShowOfferSummary(npa, offer)
154+
roflCommon.ShowOfferSummary(npa, offer)
155155
}
156156
}
157157
}

0 commit comments

Comments
 (0)