AddPriceEntry adds a price from a specific source (e.g., smart contract) This implements multi-source price validation with deviation checks
(ctx sdk.Context, source sdk.Address, id types.DataID, price sdkmath.LegacyDec, timestamp time.Time)
| 164 | // AddPriceEntry adds a price from a specific source (e.g., smart contract) |
| 165 | // This implements multi-source price validation with deviation checks |
| 166 | func (k *keeper) AddPriceEntry(ctx sdk.Context, source sdk.Address, id types.DataID, price sdkmath.LegacyDec, timestamp time.Time) error { |
| 167 | sourceID, authorized := k.getAuthorizedSource(ctx, source.String()) |
| 168 | if !authorized { |
| 169 | return errorsmod.Wrapf( |
| 170 | sdkerrors.ErrUnauthorized, |
| 171 | "source %s is not authorized oracle provider", |
| 172 | source.String(), |
| 173 | ) |
| 174 | } |
| 175 | |
| 176 | if id.Denom != sdkutil.DenomAkt { |
| 177 | return errorsmod.Wrapf( |
| 178 | sdkerrors.ErrInvalidRequest, |
| 179 | "unsupported denom %s", id.Denom, |
| 180 | ) |
| 181 | } |
| 182 | |
| 183 | if id.BaseDenom != sdkutil.DenomUSD { |
| 184 | return errorsmod.Wrapf( |
| 185 | sdkerrors.ErrInvalidRequest, |
| 186 | "unsupported base denom %s", id.BaseDenom, |
| 187 | ) |
| 188 | } |
| 189 | |
| 190 | if !price.IsPositive() { |
| 191 | return errorsmod.Wrap( |
| 192 | sdkerrors.ErrInvalidRequest, |
| 193 | "price must be positive", |
| 194 | ) |
| 195 | } |
| 196 | |
| 197 | latestID, err := k.loadLatestPriceID(ctx, types.PriceDataID{ |
| 198 | Source: sourceID, |
| 199 | Denom: id.Denom, |
| 200 | BaseDenom: id.BaseDenom, |
| 201 | }) |
| 202 | |
| 203 | if err != nil { |
| 204 | if !errors.Is(err, collections.ErrNotFound) { |
| 205 | return err |
| 206 | } |
| 207 | |
| 208 | // applies only to very first record. |
| 209 | // set here reasonable window |
| 210 | latestID.Timestamp = ctx.BlockTime().Add(-(time.Second * 12)) |
| 211 | } |
| 212 | |
| 213 | if latestID.Timestamp.After(timestamp) { |
| 214 | return errorsmod.Wrap( |
| 215 | sdkerrors.ErrInvalidRequest, |
| 216 | "price timestamp is too old", |
| 217 | ) |
| 218 | } |
| 219 | |
| 220 | seq, err := k.priceRecordSeq(ctx, types.DataID{ |
| 221 | Denom: id.Denom, |
| 222 | BaseDenom: id.BaseDenom, |
| 223 | }) |
nothing calls this directly
no test coverage detected