package mutations import ( "context" "time" "github.com/pkg/errors" "github.com/shopspring/decimal" "git.lehouerou.net/laurent/sorare/graphql" "git.lehouerou.net/laurent/sorare/types" ) type createSingleSaleOfferInput struct { Approvals []AuthorizationApprovalInput `json:"approvals"` AssetId string `json:"assetId"` ClientMutationId string `json:"clientMutationId"` DealId string `json:"dealId"` Duration int `json:"duration"` ReceiveAmount AmountInput `json:"receiveAmount"` SettlementCurrencies []types.SupportedCurrency `json:"settlementCurrencies"` StartDate string `json:"startDate"` } type CreateSingleSaleOfferParams struct { Input createSingleSaleOfferInput `graphql:"input"` } func (m *Mutations) newCreateSingleSaleOfferMutation() *graphql.Mutation[BaseMutationPayload, CreateSingleSaleOfferParams] { return graphql.NewMutation[BaseMutationPayload, CreateSingleSaleOfferParams]( m.c, "createSingleSaleOffer", ) } type CreateSingleSaleOfferOptions struct { Duration time.Duration DelayBeforeStart time.Duration SettlementCurrencies []types.SupportedCurrency } func WithDuration(duration time.Duration) func(*CreateSingleSaleOfferOptions) { return func(o *CreateSingleSaleOfferOptions) { o.Duration = duration } } func WithDelayBeforeStart(delay time.Duration) func(*CreateSingleSaleOfferOptions) { return func(o *CreateSingleSaleOfferOptions) { o.DelayBeforeStart = delay } } func WithSettlementCurrencies( currencies []types.SupportedCurrency, ) func(*CreateSingleSaleOfferOptions) { return func(o *CreateSingleSaleOfferOptions) { o.SettlementCurrencies = currencies } } func (m *Mutations) CreateSingleSaleOffer( ctx context.Context, assetId string, amount decimal.Decimal, currency types.SupportedCurrency, privateKey string, receiverSlug string, opts ...func(*CreateSingleSaleOfferOptions), ) error { options := CreateSingleSaleOfferOptions{ Duration: 2 * 24 * time.Hour, DelayBeforeStart: 5 * time.Second, SettlementCurrencies: []types.SupportedCurrency{ types.SupportedCurrencyWEI, types.SupportedCurrencyEUR, }, } if len(m.defaultSettlementCurrencies) > 0 { options.SettlementCurrencies = m.defaultSettlementCurrencies } for _, opt := range opts { opt(&options) } currencyShift := 2 if currency == types.SupportedCurrencyWEI { currencyShift = 18 } amount = amount.Shift(int32(currencyShift)) prepareOfferRes, err := m.newPrepareOfferMutation().Execute(ctx, PrepareOfferParams{ Input: prepareOfferInput{ Type: types.OfferTypeSingleSaleOffer, SendAssetIds: []string{assetId}, ReceiveAssetIds: make([]string, 0), ReceiveAmount: &AmountInput{ Amount: amount.String(), Currency: currency, }, ReceiverSlug: receiverSlug, ClientMutationId: GetRandomId(), SettlementCurrencies: options.SettlementCurrencies, }}) if err != nil { return errors.Wrap(err, "preparing offer") } if len(prepareOfferRes.Errors) > 0 { return errors.Wrap(errors.New(prepareOfferRes.Errors[0].Message), "preparing offer") } approvals, err := signAuthorizationRequests( privateKey, prepareOfferRes.Authorizations, ) if err != nil { return errors.Wrap(err, "signing authorization requests") } createSingleSaleOfferRes, err := m.newCreateSingleSaleOfferMutation(). Execute(ctx, CreateSingleSaleOfferParams{ Input: createSingleSaleOfferInput{ Approvals: approvals, AssetId: assetId, ClientMutationId: GetRandomId(), DealId: GetRandomId(), Duration: int(options.Duration.Seconds()), ReceiveAmount: AmountInput{ Amount: amount.String(), Currency: currency, }, SettlementCurrencies: options.SettlementCurrencies, StartDate: time.Now(). Add(options.DelayBeforeStart). UTC(). Format(time.RFC3339), }}) if err != nil { return errors.Wrap(err, "creating single sale offer") } if len(createSingleSaleOfferRes.Errors) > 0 { return errors.Wrap( errors.New(createSingleSaleOfferRes.Errors[0].Message), "creating single sale offer", ) } return nil }